E:\downloadZ\Delphi 8 Tutorial

The reason we use these names is because the classes directly represent ... The lines with the arrowheads indicate that both the 'Company' and 'person' ...
163KB taille 2 téléchargements 384 vues
Delphi 8 The following tutorials have been created in order to provide Borland Delphi 8 Architect customers with a step-by-step approach to how Borland Enterprise Core Objects (ECO) works. The tutorials, beginning with Tutorial 1, should ease customers into the concepts of ECO and model-driven applications and advance to more complicated features and capabilities. Please check back for more tutorial updates to this page. Tutorial 1: Creating your first ECO application Tutorial 2: Working with Associations Tutorial 3: Using Borland® Enterprise Core Objects (ECO™) with Databases

Tutorial 1 Creating your first ECO application By Anthony Richardson Abstract - This article demonstrates building a simple application using the Borland® Enterprise Core Objects (ECO)™ technology in Borland® Delphi™ Architect.



Introduction



What is Modeling?



The Example Application



Building the Application



CoreClassesUnit.pas



ContactManagerEcoSpace.pas



Building an ECO Model



Creating the Model



Adding a User Interface



Running the Application



Persisting the data



Auto Forms



Conclusion



About the Author

Delphi 8 Architect ECO Tutorial Project Introduction Enterprise Core Objects (ECO)™ is a development and runtime framework for Model Driven Development. The traditional process of transforming requirements to a computer understandable view of the problem may involve the design of databases, applications, and interfaces each with its own way of representing the business logic. ECO applies Object Oriented flexibility and design to the business and persistence layers of your application making design and development easier. It is worth spending time on this upfront because this is a huge part of the productivity enhancement you will experience when using the ECO architecture. What is Modeling? I have mentioned Model Driven Development, but what is a model? A model is a description or view of something. Like a model aircraft is a miniature representation of a real aircraft, a software model is a representation of the problem domain in which the software will run. It is possible to generate many different models for a particular software project. Popular software engineering methodologies describe models and activities at various stages of the software development lifecycle. Models also simplify communication between developers, users and other stakeholders. By creating the various types of models you can describe a complex software system in a series of progressively more detailed set of views into the problem domain. The problem with using models, in this way, is that, by the time you have increasingly refined a model to the point that it is completely unambiguous and executable, it no longer is recognizable as a description of the original problem. By the time we have converted a description of the problem progressively from text description to source code and database schemas, only a developer (and the compiler) can understand it. The problem with this is the transformation from business understanding to compiler understanding has to happen each time we modify the code. And when we look at code written by others we need to convert it the other way, from source code to business logic. ECO provides a way to remove the need to manually perform a lot of the transformation. ECO allows the developer to model a problem in a way that more closely represents the business logic, and is still unambiguous and executable. This is often referred to as raising the level of abstraction. By doing this, the ability to change and understand complex software is made easier and less expensive. When we create models in ECO the classes we model are often referred to as Business Classes or Domain Classes. At runtime we refer to these as Business Objects or Domain Objects. The reason we use these names is because the classes directly represent entities in the problem domain of the business. For example, in a University enrollment application we may model the business classes Student, Teacher and Subject. The Example Application This tutorial will build a simple address book application that saves its data to an XML file. The basic needs for our application are:



Store contact information for people.



Store contact information for companies.

We are going to implement the following Unified Modeling Language™ model for our address book application:

If you are not familiar with UML, the diagram shows three classes, represented by the rectangles. The class 'Contact' although not marked in the above diagram, is an abstract class. The lines with the arrowheads indicate that both the 'Company' and 'person' classes descend from the 'Contact' class. The model shows the following business rules:



A Contact has a name, address and phone number.



A Contact must be either a person or a Company.

For this example I could have implemented the model using one class and a simple Boolean flag to indicate if the contact was a person. I chose the above model because in the next tutorial we will extend the model and I also wanted this tutorial to demonstrate the basic generalization relationship. Building the Application



Select "Other" from the "File|New" menu.



From the "New Items" dialog, select "Delphi for .Net Projects" and then "ECO Windows Forms Application". press the "OK" button.



The New Application Dialog is displayed. Enter the name of the application. For this example use the name "ContactManager" press the "OK" button.

Borland Delphi creates a bare ECO application. The "Project Manager" (View|Project Manager) shows the automatically generated files. There are two files that are different from a normal Delphi Application. These are ContactManagerEcoSpace.pas and CoreClassesUnit.pas.

CoreClassesUnit.pas This file contains an empty "UML package". This is where the classes for our ECO application will be created by default. It is possible to create multiple packages, however, this tutorial will only use the default package. ContactManagerEcoSpace.pas This contains the "EcoSpace" for your application. An EcoSpace contains the objects of the application at runtime. It provides the link between the objects and the persistence mechanism (XML or RDBMS). The EcoSpace can be queried using OCL to retrieve objects from the EcoSpace. From the Borland Delphi help file: "An ECO Space is a container of objects. At runtime, the ECO Space contains actual instances of the classes in your model. It is helpful to think of the ECO Space as an actual instance of a model, much like an object is an instance of a class. The objects contained in the ECO Space retain the domain properties (attributes and operations) and relationships defined in the model. As a container of objects, an ECO Space is both a cache, and a transactional context. Within the ECO Space, another component called a persistence mapper is used as the conduit between the persistence layer (either an RDBMS or XML file), and the instances of the classes defined in the model. When you configure an ECO Space using the IDE, you will select those UML packages in your model that you wish to persist in the ECO Space." Building an ECO Model ECO uses a subset of the Unified Modeling Language (UML) as its modeling language. The specific parts are the Class Diagram and Object Constraint Language (OCL). Creating the Model From the "Model View" double-click the "CoreClasses" diagram item. This will open the modeling surface editor. When this opens, the "Tool palette" changes to contain the tools for generating our model.

Begin by creating a new class. You can do this one of three ways.

1.

Select the "Class" tool in the "Tool palette" and click the modeling surface.

2.

Right click the modeling surface and select Add|Class from the pop-up menu.

3.

Right click the modeling surface and select "Add New Item..." from the pop-up menu. Select the Class Template and press OK.

Once the class is created, ensure it is selected so the properties of the class are visible in the "Object Inspector" Select the name property to "Contact" and the Abstract property to "True" Borland Delphi 8 will create a corresponding Delphi abstract class called Contact.

Right-click the class and select "Add|Attribute". Select the attribute in the class with the mouse and the "Object Inspector" will display the properties for the attribute. Set this attribute's name to "fullName" and type to "String".

Add the string attribute's address and phone to the Contact class. Add the class' person and Company to the model. Leave the abstract property false as these will be the concrete classes we create instances of. We now need to create a generalization relationship between the person class and the Contact class. A generalization relationship specifies that person is a type of Contact, and inherits all the attributes and operations of Contact. To create this relationship select the "Generalization/Implementation" tool and select the person class and drag to the Contact class.

Create the same generalization relationship for the Company Class. The completed model is below.

It is interesting to take a look at the "Model View" now that we have added some classes. The Model view shows the two models in the ECO Application. The Domain Model is the model we have just created, the Implementation Model is auto generated by ECO. The Implementation Model is created as Delphi classes.

The code generated by ECO shows the large amount of implementation detail that ECO takes care of for the developer. This code allows for managing lists of each domain class, enumerator classes, adapter and all the management code for maintaining the objects within a running application. Normally, the developer is responsible for this code and it quickly turns a readable model from being a clear representation of the problem, into a mass of complex structures and architectural elements unrelated to the real problem. Adding a User Interface Now that a model has been created, it is necessary to add a simple GUI to explore the runtime behaviour of ECO. NOTE: At this point in the exercise it is important that you compile your application. ECO needs to have the model compiled so the GUI designer can display the model information. The runtime system of ECO relies on the interrogation of the classes using .Net Reflection. For Reflection to work you must compile the application. Using the "Tool palette" add the follow controls to the WinForm.pas form.



Category: Windows® Forms add 2 Buttons.



Category: Data Controls add 3 DataGrids.



Category: Enterprise Core Objects add 3 ExpressionHandles.

Set the following properties:

Type: Button Name: btnAddPerson Type: Button Name: btnAddCompany Type: ExpressionHandle Name: ehContacts Root: rhRoot Expression: Contact.allinstances Type: ExpressionHandle Name: ehPersons Root: rhRoot Expression: person.allinstances Type: ExpressionHandle Name: ehCompanies Root: rhRoot Expression: Company.allinstances Type: DataGrid Name: dgContacts DataSource: ehContacts Type: DataGrid Name: dgPersons DataSource: ehpersons Type: DataGrid Name: dgCompanies DataSource: ehCompany

Enter the following code for the buttons OnClick event code:

procedure TWinForm.btnAddPerson_Click(sender: System.Object; e: System.EventArgs); begin Person.Create(EcoSpace); end; procedure TWinForm.BtnAddCompany_Click(sender: System.Object; e: System.EventArgs); begin Company.Create(EcoSpace); end; The ReferenceHandle component, which was placed on the form by the ECO Application wizard, provides the link between the EcoSpace and the Win Form. A ReferencetHandle can be set to reference a specific object in an ECO Space or the entire ECO Space. This is how the ReferenceHandle is being used in this example. It is important to set the reference handle to use the ECO Space we have just defined in our model, set the following parameter for the rhRoot component.

EcoSpaceType = ContactManagerEcoSpace.TContactManagerEcoSpace The ExpressionHandle is linked to another handle, either an ExpressionHandle or a Referencehandle, and evaluates an OCL expression to provide a resulting object, collection or value. It is possible to daisy chain ExpressionHandles where each handle evaluates its result from the results of the previous handle. Running the Application Run the application and create some persons and Companies.

The grid set to show "person.allinstances" shows only the persons created. The grid set to show "Company.allinstances" show only the Companies created. The grid set to show "Contact.allinstances" shows both the Persons and the Companies. Persisting the Data An application like in this example would generally be required to save the entered data between each invocation. With ECO there are two basic persistence methods supported. Saving to a XML file or saving to a RDBMS. For this example an XML file will be used, as it's simpler to configure. From the "project Manager" double click ContactManagerEcoSpace.pas to call up its Design Editor. From the "Tool palette" select the 'persistenceMapperXML" tool and drop it on the designer. Set the following properties:

Type: persistenceMapperXML1 FileName: data.xml

Type: EcoSpace persistenceMapper: persistenceMapperXML1 On the WinForm.pas form add a new button. Name it "btnSave" and set the text to "Save". Add the following code to btnSave OnClick event handler.

procedure TWinForm.btnSave_Click(sender: System.Object; e: System.EventArgs); begin EcoSpace.UpdateDatabase; end; Now when you run the application the data you enter will be saved to the data.xml file each time you press the "Save" button. It's worth noting that there was no requirement within the model to specify information relating to how the data was going to be saved. However, this is possible if required. Auto Forms ECO supports the automatic generation of forms for editing your ECO Objects at runtime. The default ECO enabled Win Form includes a ECOAutoForms component. This component extends the data aware controls on your form to support double-click activation of the objects auto form. Set the auto form property of all three grids to true.

At runtime you can activate the auto form by double clicking the fixed column of any grid.

Conclusion ECO offers a way to develop applications where the developer spends more time coding the business logic and less time on architectural coding. This allows for the code to be clearer and reduces the cost of change. ECO provides a distinct separation between presentation, logic, and persistence. This reduces the effect changes have on an application.

Tutorial 2 Working with Associations By Anthony Richardson Abstract - This article demonstrates accessing Borland® Enterprise Core Objects (ECO™) objects in code via handles, implementing relationships and using master/detail style user interfaces.



Introduction



Using the CurrencyManagerHandle



Adding a relationship



The relationship at work



Conclusion



About the Author

Delphi 8 Architect ECO Tutorial 2 Introduction In Tutorial 1 (Borland® Delphi™ Architect ECO™ Tutorial 1), a simple contact manager application was described and constructed. That application will form the basis for this tutorial. Using the CurrencyManagerHandle In Tutorial 1, ExpressionHandles were used to provide lists of the core objects in the ECOSpace.™ These lists were then connected to grids to display the information. When it is necessary to determine which item in a list a user has selected, in an ECO application, you use a CurrencyManagerHandle. The CurrencyManagerHandle is a component in the Enterprise Core Objects section of the toolbox. It will track the current selected item in a list. On the Win Form of the application from tutorial 1, place a CurrencyManagerHandle and another button as per the following figure.

Set the following properties.

Type: Button Name: btnDeleteContact Text: Delete Type: CurrencyManagerHandle Name: cmhContact RootHandle: ehContact BindingContext: dgContact In the Click event handler for the Delete button place the following code

procedure TWinForm.btnDelete_Click(sender: System.Object; e: System.EventArgs); var SelectedContact: Contact; begin if cmhContact.Element.AsObject is Contact then begin SelectedContact := Contact(cmhContact.Element.AsObject); SelectedContact.AsIObject.Delete; end; end;

Run the application. When you press the delete button, the currently selected contact in the contact datagrid is deleted. Take a closer look at the code in the btnDelete_Click method.

if cmhContact.Element.AsObject is Contact then begin ... end; The conditional IF statement accesses the Element property of the CurrencyManagerHandle. The CurrencyManagerHandle.Element property is a reference to the currently selected item in the list. The result is an IElement. The IElement interface is the lowest common denominator for all possible objects that can be referenced by a handle. All ECO objects, collections, and attributes must implement IElement. The AsObject method of IElement returns the Object that is currently implementing the IElement instance. In the above example, the Object's class is being compared to the class Contact. This is done using the IS operator to ensure the CurrencyManagerHandle is referring to an object of the correct type.

SelectedContact := Contact(cmhContact.Element.AsObject); The remaining code is using a local variable of type Contact to hold a reference to the object referred to by cmbContact.Element.AsObject. The object is being cast as Contact because the previous IF statement ensures only objects of class Contact will be executed by this code.

SelectedContact.AsIObject.Delete; All classes generated by ECO implement the IObject interface. IObject gives you access to manipulate the object's state in the ECO Space. Specifically, the above code calls the Delete method to remove the object from the ECO Space. Why not use the Destroy or Dispose methods? Simply because by calling Delete, the object has all its relationships deleted and is removed from the list of normally accessible objects. However, the object has to stay in memory until the next save operation, so ECO knows to remove it from the database. Unlike normal objects, which only have the one state (created), ECO objects need to maintain their state while in memory and while they exist in the database. NOTE: Never call Destroy or Dispose on an ECO-controlled object; always use Delete to remove objects you no longer require. Adding a relationship Up until now the application has been very basic. However, one of the most important aspects of ECO is its ability to manage relationships between objects. Using the model surface, draw an association from Person to Company.

Set the following properties.

Type: Association Name: Employment End1.Multiplicity: 0..* End1.Name: employees End2.Name: employer This association allows our contact manager application to record the relationship of a company and its employees. This simple process of drawing the association has resulted in ECO generating all the code to manage the relationship from both ends. When you assign a company as an employer for a person, ECO will ensure that the Person is automatically added to the employee collection for that company. Stop and think about this. ECO now handles all referential integrity aspects of your application's relationships, both in memory and in the database. A fair amount of architectural coding of a non-ECO application has just been eliminated. The intelligent runtime systems in ECO will handle relationship navigation, caching, retrieval, and persistence. Multiplicity is the measure of the number of 'connections' at the association end-point. There are four basic options:

· · · ·

0..1: 1..1: 0..*: 1..*:

Zero or one connection. Must have one and only one connection. Zero or many connections. One or many connections.

The relationship at work To see how the relationship works, it is necessary to modify the user interface. The following steps will change the existing ExpressionHandle, for the datagrid displaying Person objects, to only display employees of the currently selected Company in the company datagrid. Also, the button used to create new Person objects will be changed to automatically add the new Person to the employee list of the currently selected company. Because the model has been modified, it is necessary to compile the application so the changes can be accessed by the GUI controls at design time. NOTE: At this point in the exercise it is important that you compile your application. Add a CurrencyManagerHandle for tracking the selected company.

Type: CurrencyManagerHandle Name: cmhCompany RootHandle: ehCompany BindingContext: dgCompany Now modify the OCL expression and root handle used for defining the person list.

Type: ExpressionHandle Name: ehPerson RootHandle: cmhCompany Expression: self.employees Changing the root handle for ehPerson to reference the new cmhCompany handle causes the handle to evaluate its expression against the currently selected Company. This is called chaining expressions. Each expression evaluates against the result of the previous expression. This is an extremely powerful capability of ECO. The expression "employees" causes the ehPerson handle to now contain a list of all employees of the selected Company. The ECO runtime system automatically handles retrieving the objects from the database without developers needing to concern themselves with how the data is retrieved. This simplifies the code dramatically for complex applications. Before running the application, we need a way to create the association between a Person and a Company at runtime. To do this, change the Click event for the btnPerson button to the following code:

procedure TWinForm.btnAddPerson_Click(sender: System.Object; e: System.EventArgs); var NewEmployee: Person; SelectedCompany: Company; begin

if cmhCompany.Element.AsObject is Company then begin SelectedCompany := Company(cmhCompany.Element.AsObject); NewEmployee := Person.Create(EcoSpace); NewEmployee.employer := SelectedCompany; end; end; The code used to extract the selected Company is similar to the code used earlier. The code used to assign the relationship in the Click event is the interesting part.

NewEmployee.employer := SelectedCompany; The process of using relationships in ECO is as simple as assigning the Company object to the employer relationship of the Person object. "So what? That's how Delphi handles all class relationships," you may say. Except in ECO, the relationship is bi-directional. Not only has the Company been assigned to the Person.employer role, the Person has been added to the Company.Employees role. This relationship is enforced and maintained by the ECO runtime system. Alternatively, the following code could have been used. The result is just the same, however the association is completed in code from the other end. The highlighted line shows the changed code.

procedure TWinForm.btnAddPerson_Click(sender: System.Object; e: System.EventArgs); var NewEmployee: Person; SelectedCompany: Company; begin if cmhCompany.Element.AsObject is Company then begin SelectedCompany := Company(cmhCompany.Element.AsObject); NewEmployee := Person.Create(EcoSpace); SelectedCompany.employees.Add(NewEmployee); end; end; Run the application, select a company and add a Person, select another company and add more Person objects. As you change between Company objects you will see the Person data grid change to show only the employees for that company. Conclusion The ECO runtime system provides an incredibly powerful system for managing objects. From managing object lifecycles to relationships, and OCL evaluations, the burden on developers to provide this functionality is removed. This allows developers to concentrate on developing business solutions rather than architectural frameworks.

Tutorial 3 Using Borland® Enterprise Core Objects (ECO™) with Databases By Anthony Richardson

Abstract - This article demonstrates connecting a Borland® Enterprise Core Objects (ECO™) application to a Relational Database Management System (RDBMS) and managing changes to the object space.



Introduction



Using ECO with databases



Modifying the application to use Microsoft SQL Server 2000



Creating a blank database



Improving the database application



Working with transactions



Implementing Object Space transactions



Separating the Object Space and Database Transactions



Analyzing the SQL created by ECO



Conclusion

Borland® Delphi™ 8 Architect ECO Tutorial 3 Project

Introduction In tutorial 2 a simple contact manager application was described and constructed. That application will form the basis for this tutorial. In the previous tutorial, the application had been persisting data to an XML file. Although this is fine for the simple applications used in the tutorials, it is hardly a robust data storage solution for enterprise applications. For that reason, included with Delphi is support for Borland® Data Providers for ADO.NET with high-performance, seamlessly "switchable" remote enterprise providers for Borland® InterBase,® Oracle9i,™ IBM® DB2,® and Microsoft SQL Server ™ 2000. ECO applications access databases using persistence mapper components. These components act as bridge between the ECO Space and specific data access components of the Microsoft® .NET Framework.

Using ECO with databases ECO is natively designed to use RDBMS as its primary choice of object storage. ECO handles the generation of the database schema, storage, and retrieval of application data, as well as maintaining database integrity by using transactions.

This tutorial focuses on converting the previous tutorial application from using an XML file to using a database. Then, this tutorial examines how to manage the changes to objects and update the database.

Modifying the application to use Microsoft SQL Server 2000 In Delphi, open the Contact Manager application from the previous tutorial. Using the Project Manager, open the ContactManagerEcoSpace.pas file and ensure that the "Design" tab is selected in the editor. The persistenceMapperXML1 component should be visible on the design surface of the ECO Space.

Delete the persistenceMapperXML component and place a persistenceMapperSqlServer component, from the Enterprise Core Component category, on the design surface. Add a sqlConnection component from the Data Controls category.

Set the following parameters:

Type: persistenceMapperSqlServer Name: persistenceMapperSqlServer1 Connection: sqlConnection1 Type: sqlConnection Name: sqlConnection1 ConnectionString: Initial Catalog=ContactManager;Data Source=localhost;Integrated Security=SSPI; Type: ContactManagerEcoSpace PersistenceMapper: persistenceMapperSqlServer1 NOTE: Don't forget to set the ECO Spaces PersistenceMapper property to the new persistence mapper component. Access this by clicking in the blank area of the design surface. This completes the required programming changes necessary to change the application from using a XML file to using Microsoft SQL Server. The connection string "Initial Catalog=ContactManager;Data Source=localhost;Integrated Security=SSPI;" instructs ECO to connect to the database "ContactManager" on Microsoft SQL Server running on the local machine. However, because the database "ContactManager" does not exist, it must be created.

Creating a blank database ECO can generate the database schema for the application, but it requires a blank database to which to connect. Using SQL Server Enterprise Manager, connect to your local server, and create a new database called "ContactManager". (The tutorial assumes you are running Microsoft SQL Server on the same machine as Delphi. If this is not the case, you must modify the connection string as appropriate).

On the bottom left corner of the design surface for the ECO Space, there is a Create Database button. Click this button. A dialog box appears showing a list of tables that must be deleted and/or recreated. This list will be empty for the first schema generation. Click OK to proceed with the schema generation. If the database contains any data, that data will be lost.

The Delphi message window indicates the result of the process. If you run the application, it will now save and retrieve data from the MS SQL Server.

Improving the database application You might have noticed that the current application cannot cancel changes that have been made. Although we would like to think that users never make data-entry errors or change their minds, the reality is that the ability to cancel changes is an expected feature of database applications. To facilitate this new functionality a main menu must be added to the application and the current save action moved to the menu. Add a Main Menu component to the WinForm.

Use the in-place menu editor to add the following menu items:

Type: System.Windows.Forms.MenuItem Name: mnuDatabase Text: Database Type: System.Windows.Forms.MenuItem Name: mnuSaveChanges Text: Save Changes Type: System.Windows.Forms.MenuItem Name: mnuCancelChanges Text: Cancel Changes Type: System.Windows.Forms.MenuItem Name: mnuDivider1 Text: Type: System.Windows.Forms.MenuItem Name: mnuGenerateSchema Text: Generate Schema Create the following "Click" events for each menu item.

procedure TWinForm.mnuSaveChanges_Click(sender: System.Object;

e: System.EventArgs); begin // Save all changes in the objectspace // to the database EcoSpace.UpdateDatabase; end; This is the same code as the previous save method.

procedure TWinForm.mnuCancelChanges_Click(sender: System.Object; e: System.EventArgs); begin // Loop through all changes to the EcoSpace and // undo the change. while EcoSpace.UndoService.UndoList.Count > 0 do begin EcoSpace.UndoService.UndoLatest; end; end; The menuCancelChanges_Click() event adds support to discard changes that have occurred in the object space. It is possible in ECO to create multiple check points for undo operations and the above method ensures that all changes since the last database update are undone. Undo will be covered in more detail in future articles (although it is not difficult to work out by looking at the IUndoService interface). It is also possible to generate the database schema using code. Add the following method to the ContactManagerEcoSpace class in EcoSpace.cs

procedure TContactManagerEcoSpace.GenerateSchema; begin self.persistenceMapperSqlServer1.CreateDataBaseSchema; end; Enter the following code in the click event handler for the "Generate Schema" menu item.

procedure TWinForm.mnuGenerateSchema_Click(sender: System.Object; e: System. EventArgs); var SavedState: Boolean; begin SavedState := EcoSpace.Active; if SavedState then begin // All changes must be saved before // closing EcoSpace. EcoSpace.UpdateDatabase; EcoSpace.Active := false; end; // Generate the database schema EcoSpace.GenerateSchema; // Restore the active state of the EcoSpace EcoSpace.Active := SavedState; end; Pressing this menu item causes ECO to regenerate the database schema, which destroys all data saved in the database. Remove the Save button and its event handler, as they are no longer required. The menu item just created now performs this duty. If you run the application, you will see that it is possible to cancel any pending changes, reverting the application state to what is was after the last database update. The conversion is now complete. The application uses Microsoft SQL Server 2000 as its storage mechanism instead of XML files. When the application runs it will connect to Microsoft SQL Server and store and retrieve all data from the "ContactManager" database. ECO automatically converts the OCL expressions to SQL, eliminating the need for the developer to keep changing between the problem domain model and the relational database storage format of the application's data.

Working with transactions When you call EcoSpace.UpdateDatabase, ECO starts a database transaction, sends one or more SQL requests to the server, and then commits the transaction. If an error occurs during the transaction, the ECO Space reflects the state of the application before the UpdateDatabase operation; that is, the unsaved changes will still exist and still require saving. This level of transaction support might not be sufficient for your needs. Fortunately, support for transactions in ECO extends beyond updates to the database. ECO provides its own mechanism for encapsulating changes that occur within the ECO Space. These transactions are native ECO transactions; however, during a database update, ECO also wraps all database changes within a database transaction.

Implementing Object Space transactions Implementing transactions in an ECO Space is simple; there are only three method calls.

IUndoService.StartTransaction; IUndoService.CommitTransaction; IUndoService.RollbackTransaction; If you are familiar with how database transactions work, then the operation of the above methods will be obvious. Use StartTransaction; to begin a transaction. ECO specifically tracks all changes made to the object space from the start of transaction until a transaction is completed. A transaction can be completed in one of two ways. By calling CommitTransaction; all the tracked changes will be applied to the object space as

a single undoable event. If RollbackTransaction; is called, then all the changes since the start of the transaction will be lost, and the object space reverts to how it was before the transaction started. It is important to use transactions in a way consistent with how Borland designed them. Transactions are designed to be short lived and should be used in a manner similar to the following code.

EcoSpace.UndoService.StartTransaction; try // Code that does stuff here EcoSpace.UndoService.CommitTransaction; except EcoSpace.UndoService.RollbackTransaction; raise; end; ECO will raise an exception if you call commit or rollback without a transaction active. The transaction API specifically does not include a method to check whether a transaction is active or not. This is by design; the state of a transaction should be implicit in the code. The above example is like that; keeping the transaction methods calls together in an exception-handling framework implicitly controls the transaction state. In the previous paragraphs the ground rules for using transactions were laid out. Keep them short-lived and keep the state implicit by the design of the code. To keep them short-lived means that the duration of the transaction must be relatively discernable from the code. To achieve both goals generally requires ensuring that no user interactions occur while a transaction is active. Although ECO can handle user interactions during an active transaction, there are reasons to avoid them. When a transaction is active, the undo mechanism of ECO is not used. This is an all- or-nothing approach to object space changes. If you commit a transaction, all changes are applied. Conversely, if you roll back a transaction, all changes within the transaction are lost. You cannot undo individual changes within a transaction. In fact, when you make changes outside of a transaction, ECO creates a small transaction for each of those changes. The result is that when you do bulk object space changes, many transactions are being started and committed. If the bulk update is placed within a single transaction, these smaller transactions will not occur, and ECO will perform changes to the object space much faster.

TIP: When performing bulk changes to the object space, use transaction to speed up the time it takes to apply the changes. Separating the Object Space and database transactions When you call "Commit Transaction", the transaction is committed to the ECO Space only. Calling "Cancel Changes" will rollback any changes that occurred in the transaction, even if the transaction is committed. At first this seems strange, but it is done for a reason. The concepts of the ECO Space and data storage are two separate concerns. Transactions concern themselves purely with the object space and persistence operations concern themselves only with the database. The separation is necessary because transactions work on all ECO objects, even transient objects. ECO applications have no specific requirement to even use a database.

Analyzing the SQL created by ECO As mentioned, all update operations to the database are wrapped in database transactions. It is possible to monitor all operations the ECO application performs on the database by using the SQL profiler application included with Microsoft SQL Server. The link to the Profiler application is in the Microsoft SQL Server folder of the start menu. The following screen shot shows a save of a new person object to the database. The analyzer application shows the transaction and SQL commands required to perform the update.

Conclusion The layered architecture of ECO makes it simple to change the storage mechanism used to persist data. The layered architecture also provides a separation of concerns between changes made to the object space and changes made to the database data. About the Author Anthony Richardson is the director of Viewpoint (SA) Pty Ltd. Anthony has many years of experience working with Borland MDA technologies. Anthony's contact details are available at http://www.viewpointsa.com.