See also Part Two
Borland Delphi 2005 Architect contains a featureset called Enterprise Core Objects 2, which allows us developers to create applications based on a model (with objects, inheritance and associations), which can be made persistent in a DBMS, and used to create GUI as well as web applications.
This month I'll introduce Enterprise Core Objects in Delphi 2005 Architect, and show how to build the model to create and maintain weblog entries (and feedback). After designing the model, I'll explain and demonstrates how to make the instance of the model - called the EcoSpace - persistent in a database like SQL Server, Interbase or any other ADO.NET or BDP compliant DBMS. Next month, we'll build the ASP.NET user interface on top of the EcoSpace model.
ECO ASP.NET Web Application
If you have Delphi 2005 Architect (or the trial edition), feel free to play along. I will not only explain what I'm doing and why, but also offer clear steps along the way. First of all, we need to create a new ECO project. Since a weblog application is - as the name indicates - a web application, we create an ECO ASP.NET Web Application. The alternatives when using ECO are a WinForms application, or an ECO ASP.NET Web Service application. Neither will do it, although the ECO WinForms application might come in handy to maintain the blog entries from a local machine (instead of the internet), but that's a story for another day.
Start Delphi 2005, and select File | New - Other which will show the Delphi 2005 Object Repository. ECO is only available for Delphi for .NET or C# projects, but not for Win32 targets.
Figure 1. Delphi 2005 Object Repository
From the Delphi for .NET Projects category, select the ECO ASP.NET Web Application (see Figure 1) and click on OK.
Before creating the ECO project, this will first present you with the ASP.NET Web Application wizard, asking you where to place the project and which web server to use for local testing and debugging.
As a name for the project, I've specified Weblog, which will be placed in the local c:\inetpub\wwwroot\Weblog directory. The name Weblog will also return as the name of the code behind assembly Weblog.dll in the Bin subdirectory of my Weblog directory.
Figure 2. NEW ECO ASP.NET Web Application Dialog
As the choice for the Web Server, we can either select Internet Information Server (IIS) if it is available on your machine or the Cassini Web Server. The latter is provided as a C# demo project with Delphi 2005 (in the BDS\3.0\Demos\Cassini directory), but should in my opinion only be used if you do not have IIS, or if you have problems using IIS as your local web server. The reason why I prefer to use IIS is that IIS will most likely be the deployment web server for your application. Cassini is only meant as a personal (test) web server, and not for real-world deployment. And if you test your application with Cassini and it works fine, you may be surprised to find that it doesn't work in the "real world", when deployed against IIS. To avoid these surprises, I always test with IIS right from the start.
Anyway, once you click on the OK button in the New ECO ASP.NET Web Application dialog, the Weblog ECO ASP.NET project is finally created for you.
Note: before we continue, I've found it sometimes
necessary with ECO projects to compile, save and
close the project, and then reopen it so the ECO
types are known to the relevant components in the
entire application. So, do Project
| Build Weblog,
then File | Close All, and say Yes when asked to
save changes to the project Weblog. Then, you can
reopen the project. This issue may have been fixed
by the time you read this, but it only takes a second
or two and I'd rather be safe than sorry. |
Step #1 - The Model
Let's first start to define the model for our weblog application. For this, we need to click on the Model View tab of the Project Manager. Open the treeview with the model nodes, and select the CoreClasses node. Expand this node, and select the CoreClasses leaf node inside. This is the node that we can use to draw the UML diagram for our ECO model. Double-click on the CoreClasses leaf node in the Model View to start the UML Designer.
Figure 3. UML Designer
When the UML Designer is shown, the Tool Palette will contain the ECO Class Diagram "drawing" controls that we can use to create a new ECO Package, a new ECO Class, an Association between two classes, a Generalization/Implementation relation between two classes (i.e. if one class is derived from another), a Note and a Note Link.
ECO Classes and Attributes
Apart from these controls in the Tool Palette, we can also right-click on the UML Designer and use the pop-up menu to Add a new ECO Package or ECO Class. For our weblog example, right-click on the designer, and Add a new ECO Class. Change the name to Entry. A weblog entry can be a post (by the main author) or a comment (by a visitor). So the Entry class is like a base class for both.
We can add attributes and operations to an ECO class. Obvious attributes for a weblog entry are the author, title and the date it was posted. So, right-click on the Entry class, and add a new attribute called Author of type String. Right-click again and add a second attribute called Title of type String, and finally a third attribute called Posted of type DateTime.
Figure 4. ECO class
Derived Classes
The Entry class is not one that we will use directly.
Instead, we should derive two other classes from it:
Post and Comment. In fact, we should mark the Entry class
as abstract by setting its abstract property to True
(so no instances of it can be made).
Then, we can add a new class called Post. We don't have to add the Author, Title and Posted attributes, since Post will be derived from Entry. This is done with the icon in the Tool Palette that says "Generalization/Implementation". Click on this icon, then on the Post class (the derived class), and finally on the Entry class (the parent class). Note that the order matters!
Figure 5. ECO Classes
There is a new attribute that we should add to Post: Contents of type string. If you look at the properties for the Contents attribute, you may notice the Length property, which is set to 255 by default. A string of only 255 characters seems a bit short to store a blog entry, so I've changed the Length property of the Contents attribute to 4096, which is probably long enough (famous last words). Note that a value of 8192 fails to generate a database schema (been there, done that), although you may want to experiment to find an optimal maximum for the Contents size.
Note: do not use Content (singular)
as the name of the attribute, as this will clash
with an internal field in the ECO class called _content.
Each attribute is stored in a strict protected field
with the name of the attribute and an underscore
prefix. Unfortunately, since there is also a _content field
in the ECO class, we cannot add an attribute called
Content. |
After finishing the Post class, we can add another class derived from Entry, this time called Comment. Use the Generalization/Implementation to reflect the fact that the Comment class is derived from the Entry class, just like the Post class is.
The Comment class also has an attribute for the contents, this time called Comments of type string, with the Length property to 1024 (so I'm not allowing people to comment as much as I post myself).
Operations
Where the attributes can be seen as properties, the ECO Classes can also have operations. These can be seen as the methods of an ECO Class. Although you define the operation at the model level, you can implement it using Delphi code.
As an example, for each weblog entry, I want to report the number of words in the contents of the Post. In order to add an operation, we must first click on the ECO Class itself, but not in the attribute area (since that will select one of the attributes). Make sure the Post class itself is selected, as shown in Figure
5.
When the ECO Class is selected, you can right-click on it and do Add
| Operation. Set the name of the new operation to WordCount. If you don't set the Returns property as well, the operation will be a procedure. But since we want it to return the number of words, change the Returns property to integer. Alternatively, you could have entered "WordCount: integer" inside the text area for the new operation in the ECO Class. The brackets will be added automatically.
In order to implement the WordCount operation, right-click on it and select the "Go to Definition" option. This will bring you to the following source lines inside the Post class definition in the CoreClassesUnit.pas source file:
[UmlElement]
function WordCount: integer;
In order to jump to the implementation of this function,
hold down the control key and move the mouse cursor over
the WordCount name, which will turn the WordCount name
into a hyperlink. Hold down the Control key, and when
you click on the WordCount hyperlink, you'll jump to
the bottom of the CoreClassesUnit source file, where
the empty WordCount function is waiting to be implemented.
A simple implementation of the number of words inside the content is as follows:
function Post.WordCount: integer;
var
InSpace: Boolean;
C: Char;
begin
Result := 0;
InSpace := True;
for C in _Contents do
if C <= #32 then InSpace := True
else
if InSpace then
begin
InSpace := False;
Result := Result + 1
end
end;
Note that I'm using the new for-in-do language feature
here, to iterate over the characters in a string. Also
note that we won't be testing the WordCount function
this month, so if I made a mistake, we won't find out
until next time.
The UML Model with the abstract Entry class and the two derived classes Post and Comment should now look as follows:
Figure 6. ECO Class Hierarchy
Although this might be enough to have a list of weblog entries posted, there are some things missing. Most weblogs out there seem to place their posts in categories. So, right-click on the UML Designer area and add a new class, called Category. The Category class gets only one attribute, called Name of type String.
The Category class has no relationship with the Entry, Post or Comment classes, yet. For that, we need to add an association between classes.
Associations
Posts can fall into one or more Categories. Zero or more, actually, unless you want to include a miscellaneous Category (which I won't, so let's assume it's 0 or more). Vice versa, a Category can contain 0 or more Posts. This relationship between Posts and Categories can be added to the model using an association. The association can be found in the Tool Palette, and the way to add it is fairly simple: click on the association icon in the Tool Palette, then click on the class you want to associate, and finally click on the class you want the first class to associate with. So first the association icon, then for example Category, and finally the Post class.
An association has properties that we can set to make it more descriptive, like the name. I've changed the name from Association_1 to Categorization. Next, we should examine both ends of the association. They also both indicate 0..1 as multiplicity. Meaning that zero or one Post belongs to zero of one Category. That has to change. At the Post end, change the 0..1 into 0..* to indicate that a Category has zero or more Posts. At the Category end, also change the 0..1 into 0..* since a Post can fit into zero or more categories.
The names that are used at the End points of the association should also end. Right now, they are Post and Category, but I've changed those names to Posts and Categories (to indicate that it can be 0 or more - likely more than 1).
This leads to the following version of the UML Model in the designer:
Figure 7. Associated Classes
There's still one more thing missing: the fact that a Comment should be associated with a Post (otherwise it wouldn't make much sense to comment, would it?). So, add an association between the Comment class and the Post class, and call it Commentary.
A Comment can be applied to only (exactly!) one Post, but a Post can have 0 or more comments, which is depicted as follows:
Figure 8. Final ECO Model
Although there are several additional enhancements possible, from comments commenting on comments, and Posts to follow-up on other Posts, and using a separate class to model the Authors, with all kinds of Author specific attributes, I leave the model as it is right now. We can always enhance and extend it later, and the best thing is that ECO will allow us to evolve the database and application when the model itself evolves. So that's true RAD, without having to throw everything away to start all over again.
At this time, we should save compile and our work, and get ready for step #2 - configuring the database to hold the model.
Step #2 - The Database
The classes that we've defined, will come to live in an environment called the EcoSpace. This EcoSpace is like the universe where instances of these classes (the objects) are created and interact with each other through associations. The EcoSpace can be made persistent by storing it inside an XML file (for single-user ECO applications) or a DBMS. The latter is the only solution for ASP.NET ECO applications, where multiple users can work on the EcoSpace simultaneously.
A PersistenceMapper component takes care of mapping the EcoSpace to a persistent file or database. In a multi-user environment, the PersistenceMapper must also take care of synchronization issues between multiple instances of an EcoSpace, and must then be placed on a PersistenceMapperProvider.
Use the Project Manager to open the EcoPersistenceMapperProvider.pas unit of the Weblog project. When you open this unit, it also has a Design tab, where we can place the PersistenceMapper component that we want to use. There are two multi-user aware PersistenceMapper components: PersistenceMapperBdp, and PersistenceMapperSqlServer. The third one, PersistenceMapperXml, can only be used in single-user ECO applications, as mentioned before.
The PersistenceMapperSqlServer works with Microsoft SQL Server using ADO.NET, while the PersistenceMapperBdp uses the Borland Data Provider for .NET, which offers connectivity to Microsoft SQL Server / MSDE, as well as InterBase, Oracle, IBM DB2, Informix, Sybase, and MS Access, plus additional third-party BDP drivers.
In this case, I want to use Microsoft SQL Server, and since the BDP components do not offer connection pooling support for SQL Server, yet, I prefer to use the SQL Server specific PersistenceMapperSqlServer component, which uses the SQL Server ADO.NET drivers from Microsoft (and support Connection Pooling).
ECO Database
First of all, we need to create the external database, so we can connect to it. This process differs from one database to another, so consult your DBMS documentation for more help. I usually prefer to use the command-line tools that are included with the DBMS to execute a "CREATE DATABASE" command.
For SQL Server, this commandline tool is called osql, which can also take a command-line script file with SQL commands. So, I've first prepared a little SQL script file with the following two lines:
CREATE DATABASE Weblog
GO And with that script file saved in weblog.sql, I can run the osql command-line tool as follows:
osql -E . -i weblog.sql
As a result, osql will report that it has created a Weblog database as well as a Weblog_log logfile for the database.
Connecting to the Database
Once the database is created, we can return to Delphi
2005 and the EcoPersistenceMapperProvider unit. We need
to place a SqlConnection component on the design area
of the EcoPersistenceMapperProvider, and specify a valid
ConnectionString to connect to the weblog database. If
you double-click on the ConnectionString property of
the SqlConnection component, the Data Link Properties
dialog will pop-up. Here, we can select the server name,
specify a username and password, and select the database
on the server. Make sure to click on the "Test Connection" button
to verify that you can make a connection to the database.
Note: do not select the "Use Windows NT Integrated
security" option, since that will work at design-time,
but may not work at runtime, especially when using
SQL Server and IIS on a Windows XP or Windows 2003
web server. Always use a specified name and password
to connect to the database. |
Figure 9. Data Link Properties Dialog
The Model and the Database
Once the SqlConnection component is configured, we can place a PersistenceMapperSqlServer component on the EcoPersistenceMapperProvider. Right-click on the PersistenceMapperSqlServer component and select "SQL Server setup", to prepare it for SQL Server. Then, point the Connection property of the PersistenceMapperSqlServer component to the SqlConnection component, and set the SyncActive property to True.
Finally, click on the design area of the EcoPersistenceMapperProvider and in the Object Inspector verify that the PersistenceMapper property points to the PersistenceMapperSqlServer component.
The only thing left to do now, is creating the database schema, based on the model. For this, there are two buttons in the lower-left corner of the designer area of the EcoPersistenceMapperProvider: Generate Schema, and Evolve Schema. We may use the latter next month (if we decide to update the model), but right now, we only need to generate the schema (for the first time). So, click on this button, which will pop-up a dialog with the actions that will be performed in the database.
Figure 10. Generate Schema
If the database was not empty, then any existing table with a conflicting name (i.e. a name of a table that has to be created) will be marked as required to drop/recreate. Any existing table with a name that doesn't conflict will be listed in the "optionally delete" tab. So you can either keep existing tables in an ECO database (although not recommended), or make sure that all tables are deleted and/or recreated when the new schema is generated.
Note that each ECO class gets its own table (Entry, Post, Comment and Category), as well as the Categorization association (which is of type many-to-many), but not the Commentary association (which is of type one-to-many).
Click on OK to create the database tables, and then compile and save the project. We've completed the design of the weblog model, and also ensured it will be made persistent in a SQL Server database. The project source files are available for download, but require Delphi 2005 Architect to compile.
Feel free to experiment with the model or PersistenceMapper components, and stay tuned for next time when we continue with the user interface of the weblog application.
Next month, I'll build the user interface on top of the EcoSpace model. Obviously, a weblog application should run as a web application, so we started this time by creating an ASP.NET ECO Web Form application. Next month, we'll build multiple pages on top of the objects in the EcoSpace, showing weblog posts in categories, and allowing visitors to leave comments (storing the comments also in the EcoSpace). And I'll also make sure to cover deployment details and issues, as well as links to the actual deployed weblog application.
All this and more next time, so stay tuned...
Continued in Part
Two
Copyright © 2005 Bob Swart
|
Bob
Swart (aka Dr.Bob - www.drbob42.com)
is an author, trainer, developer, consultant and
webmaster for Bob Swart Training & Consultancy
(eBob42) in The Netherlands, who has spoken at
Delphi and Borland Developer Conferences since
1993. Bob has written chapters for seven books,
as well as the Borland Delphi 8 for .NET Essentials and Delphi
8. ASP.NET Essentials courseware manuals licensed
by Borland worldwide, and is selling his updated
Delphi 2005 courseware manuals online at http://www.drbob42.com/training.
Bob received the Spirit of Delphi award at BorCon
in 1999, together with Marco Cantù. |
June 2005 |