In this article, I want to demonstrate how you can use the Architect edition of Borland® DelphiTM 8 for the Microsoft® .NET Framework (abbreviated to "Delphi 8 for .NET"), and specifically the functionality found in the Borland Enterprise Core Objects (ECOTM) section, to design an Object Model that is made persistent inside the IBM® DB2® Universal DatabaseTM (UDB) SAMPLE database.
Starting with ECO
The Enterprise Core Objects functionality is only available in the Architect edition of Delphi 8 for .NET.
Do File | New - Other, and select the ECO Windows Forms Application icon from the Delphi for .NET Projects page of the Object Repository (see Figure 1).
Figure 1. Delphi 8 for .NET Object Repository
This presents you with a dialog where you can specify the name and location of the new ECO project (see Figure 2).
Figure 2. New ECO Application
The DB2ECO project consists of three units: CoreClassesUnit.pas, DB2ECOEcoSpace.pas, and WinForm.pas, as can be seen in the Project Manager. The Project Manager pane has three tabs: one for the Project Manager (the default view), one for the Model View, and one for the Data Explorer. The Model View is especially useful for ECO projects (see Figure 3).
Figure 3. Model View
The CoreClasses package node (with the gray folder icon) contains a CoreClasses diagram node. Double-click on the CoreClasses diagram node to start the UML Designer in the Delphi 8 for .NET IDE. This is the place where you can design your objects using UML techniques. For example, by right-clicking on the UML Designer, you can create new classes, and inside classes you can add attributes, operations, or constructors. Furthermore, you can use the drawing components from the special UML Class Diagram category of the Tools Palette (see Figure 4).
Figure 4. UML Class Diagram
Building the object model
With these building blocks, you can build an object model. As an example, right-click on the UML Designer and create a new class. Call it Person. Right-click on Person and add four attributes: FIRSTNME, MIDINIT, LASTNAME, and SEX of type string. Note that unlike a database table, there isn't a way to specify the length of the string attributes - only the option to specify that they are of type string. Now, right-click again and add a fifth attribute, this one called BIRTHDATE of type DateTime. Note that this type will automatically be changed to System.DateTime by the Object Inspector.
Apart from the generic Person class, I also want to add a more specific Employee class - one that mimics the layout of the EMPLOYEE table from the DB2 UDB SAMPLE database, for example (which may explain the attribute names I used inside the Person class). So, right-click on the UML Designer and create a new class, this time called Employee. Since an Employee is a specialized Person, you should click on the Generalization/Implementation drawing component from the UML Class Diagram category of the tool palette, and then draw a line from the new Employee class to the Person class. This will depict the fact that Employee is derived from Person - both in the UML Diagram as well as in the Delphi source code.
Of course, an Employee has some specific attributes as well, so right-click in the Employee class and add four new string attributes called EMPNO, WORKDEPT, PHONENO, and JOB. Also add a System.DateTime attribute called HIREDATE, a Smallint attribute called EDLEVEL, and finally three Decimal attributes called SALARY, BONUS, and COMM. This results in the small UML Diagram seen in Figure 5.
Figure 5. UML Model
I leave it as an exercise for the reader to extend the UML Model. A good practice would also be to model the other tables from the IBM DB2 UDB SAMPLE database (like the DEPARTMENT table, or the EMP_ACT, EMP_PHOTO, and EMP_RESUME tables - integrating the latter into the Employee class).
Persisting the model in DB2
Apart from offering a UML Designer, the Enterprise Core Objects in Delphi 8 for .NET also offer the ability to make this object model persistent. This can be done inside a simple XML file, or in a real DBMS - like IBM's DB2 UDB.
For the persistent capabilities, you need to move to the DB2ECOEcoSpace.pas unit in the Object Manager. This unit defines your EcoSpace, and can be customized with components from the Enterprise Core Objects category in the Tools Palette. Specifically, you may want to look at the three PersistenceMapper components: PersistenceMapperXml, PersistenceMapperSqlServer and PersistenceMapperBdp. The PersistenceMapperXml component can save the EcoSpace inside an XML file, while the other two save the EcoSpace inside a DBMS. For DB2, you must use the PersistenceMapperBdp component, so drop one on your EcoSpace module.
There are three steps that you have to perform in order to make your application use this component. First of all, you need to configure the SqlDatabaseConfig property, which by default contains an <<EMPTY PERSISTENCE MAPPER CONFIG>> value. You can specify a correct value by using one of the verbs at the bottom of the Object Inspector. Since you want to use DB2 as a persistence database, you must click on the DB2 setup link. Clicking on this verb doesn't seem to do much (no dialog is started), but if you look again, you'll notice that the SqlDatabaseConfig property has now assigned a value specifically for the DB2 setup.
The next step involves a BdpConnection component that maps to the specific DB2 UDB database that you want to use to store your object model. From the Data Explorer, simply drag the Db2Connection to the DB2 UDB SAMPLE database to your EcoSpace module. This will result in a BdpConnection component that is configured to use the IBM DB2 UDB SAMPLE database. Now select the PersistenceMapperBdp component and point its Connection property to the BdpConnection component.
Now you only need to tell your EcoSpace module to use the PersistenceMapperBdp component as its PersistenceMapper (that is, as the way to make the model persistent), so click on the EcoSpace module, and in the Object Inspector select the PersistenceMapperBdp as the value for the PersistenceMapper property. Note that you can set this property dynamically at run-time, allowing you to switch from persistence strategy (for example, using a stand-alone XML persistence file when not connected to the network and DB2 UDB database - as local briefcase model - and then reconnecting to the DB2 database as persistence method when back in the office).
Generating DB2 schema
You're almost done with making the model persistent. What's missing is the actual link between your UML model and the database schema. Although the IBM DB2 UDB SAMPLE database already contains a table called EMPLOYEE, this table is not directly compatible with the EMPLOYEE class from your UML model. In order to automatically create the right database schema (in this case, for the DB2 SAMPLE database) you should click on the lower-left button on the EcoSpace module which generates the database schema, telling you which tables need to be recreated (in case their corresponding class definitions have been modified inside the UML Model) and which tables could be dropped - if you wish to do so - since they are not used by the UML Model, and hence considered "unnecessary" by the system.
In your case, with the default IBM DB2 UDB SAMPLE database, the list of tables to (optionally) delete can be seen in Figure 6, which also displays the PersistenceMapperBdp, BdpConnection components, and the Enterprise Core Objects components in the Tools Palette.
Figure 6. Generate Schema
More interesting than the tables that you can delete (which should be none) are the tables that have to be deleted and recreated. For these tables, there is no choice, and in your case this means that the EMPLOYEE table will be recreated (see Figure 7). The previous EMPLOYEE table with all data will be dropped, and a new EMPLOYEE table will be created, along with a new PERSON table (but since there isn't a PERSON table already, it doesn't need to be dropped).
Figure 7. Tables that must be deleted/recreated
If you ever make changes to the UML Model, you can recreate the database schema in order to make sure the database tables and UML Model are back in sync.
After generating the database schema, the DB2 UDB SAMPLE database will have a new version of the EMPLOYEE table, as well as a PERSON table and six new ECO-specific tables called ECO_ID, ECO_MEMBERMAPPING, ECO_R_CLSMAP, ECO_TABLES, ECO_TYPE, and ECO_W_CLSMAP.
Working with the object model
I've shown you how to define an object model using the UML Designer, and how to make the EcoSpace persistent using the PersistenceMapperBdp component. But I haven't shown you how to actually use the objects in the EcoSpace. For that, let's move to the WinForm.pas unit, which already contains five ECO components in the non-visual component area of the designer.
You need to add an additional component from the Enterprise Core Objects category, namely an ExpressionHandler. Point the RootHandle property of the ExpressionHandler to the rhRoot component. Using the ExpressionHandle, you can build OCL expressions that can be displayed; for example, the collection of all Employees or Persons inside a DataGrid. To build OCL expressions, select the ExpressionHandle component and double-click on the Expression property, which will give you the OCL Expression Editor (see Figure 8).
Figure 8. OCL Expression Editor
As an example, I've built the EMPLOYEE.allInstances expression, but you can also build the PERSON.allInstances expression or any other OCL expression that you want to display.
To actually display the result of this OCL expression, you can use a DataGrid control from the Data Controls category of the Tool Palette, with its DataSource property pointing to the ExpressionHandler component. This will result in the display shown in Figure 9.
Figure 9. WinForm with DataGrid
There's one more thing you may want to do: although the current application shows you all Employees inside a DataGrid, with the option to edit them and make them persistent, you still need a way to create a new Person or Employee (so they are displayed in the DataGrid where you can edit them).
For this, drop a button on the Windows Form, set its Text property to "New" and write a single line of code in the Click event handler:
procedure TWinForm.Button1_Click(sender: System.Object; e: System.EventArgs); begin Employee.Create(EcoSpace) end;
At first this feels a bit strange, since you create something but you're not using it. But if you look closely, you'll notice that you create a new Employee in the context of the EcoSpace - which means it will live on in the EcoSpace, and will be shown in the DataGrid (since this one is connected to the OCL expression EMPLOYEE.allInstances).
The last step involves the explicit action to save the model (and make it persistent inside the IBM DB2 UDB SAMPLE database). Drop a second button, set its Text property to Save and write the following one-liner again in the Click event handler:
procedure TWinForm.Button2_Click(sender: System.Object; e: System.EventArgs); begin EcoSpace.UpdateDatabase end;
This will make the model persistent and update the IBM DB2 UDB SAMPLE database tables for you.
In this article, I've shown that IBM DB2 UDB is a powerful DBMS that can be used as a persistence layer for the Enterprise Core Objects of Delphi 8 for .NET to build persistent object models. The integration with ECO and DB2 UDB is seamless and results in powerful model-driven applications.