Update and Maintain dbExpress's Unidirectional, Read-Only Datasets (cont'd)


Read-Only, Unidirectional Datasets
To understand the unidirectional, read-only datasets that dbExpress provides, let's build a dbExpress application with Delphi 6. First, do a File | New and select CLX Application (a cross-platform application, which will also compile on Linux using Kylix). Drop a TSQLConnection component on the CLX form and set its ConnectionName to IBLocal. To ensure the database is pointing to an actual InterBase .gdb file, you may have to right-click on the SQLConnection component and start the Connections Editor. And of course the password for SYSDBA is masterkey (just in case someone in the community doesn't know that yet).

Next, drop a TSQLTable component and set its SQLConnection property to the SQLConnection1 component. Select one of the available tables in the TableName property. We now have a read-only, unidirectional dataset. This is nice when connecting to a DataSetTableProducer component (in which case we need to walk through the resultset only once anyway), but not so useful in most other situations.

In order to display the information from the TSQLTable (or any dbExpress dataset), we need to cache it inside a TClientDataSet component using a TDataSetProvider component as "connector." So drop both a TDataSetProvider and a TClientDataSet component from the Data Access tab of the Component Palette. Assign the SQLTable component to the DataSet property of the DataSetProvider, and then assign the name of the DataSetProvider to the ProviderName property of the ClientDataSet.

As soon as you open the ClientDataSet (for example by setting the Active property to True), the content of the TSQLTable will be traversed (just once) and the records in the resultset will be provided to the ClientDataSet, which will cache them from that moment on. We can now use a DataSource and, say, a DBGrid component to display the contents provided by the ClientDataSet component.

Solutions for the Update Problem
The update problem occurs after we run the resulting application, make changes to some of the fields and records, and exit the application again. When we restart, we see the old values again. The ClientDataSet is great for caching, but it didn't update the actual database for us.

Since the TSQLTable component itself is read-only and cannot Post (or even Insert/Edit) using the TSQLTable component, we should use the ClientDataSet, which can utilize the DataSetProvider to connect back to the original dbExpress database. The method we should call is ApplyUpdates, so we can drop a TButton on the Form and set its Caption property to Apply Updates (Figure 1 shows a form with the caption).

Inside the OnClick event handler for the Apply Updates button we should write one line of code:

procedure TForm1.Button1Click(Sender: 
TObject); begin ClientDataSet1.ApplyUpdates(-1) end;
Figure 1  
Figure 1. Button with Apply Updates Caption (Click to enlarge)


This will send all pending updates (inside the ClientDataSet) back to the original dbExpress database. It also will return a "reconcile" error if an update error occurs (e.g., when a record has already been changed by another user). In that case, we must respond to the OnReconcileError event of the ClientDataSet, but that's a story for another day.

Although the presented solution will work, you cannot realistically expect your customers and end users to always remember to click the Apply Updates button when they want to save their work. One solution is to make it an automatic (apply) update: respond to the OnAfterPost event handler of the ClientDataSet component and call ApplyUpdates after each implicit or explicit Post event:

procedure TForm1.ClientDataSet1AfterPost(DataSet: TDataSet);
begin
  (DataSet AS TClientDataSet).ApplyUpdates(-1)
end;
Although this solution may seem complete already, we still need to consider other situations. What about deleting records, for example? There is no Post event after you delete a record, so you should also implement the OnAfterDelete event handler by calling the same ApplyUpdates method.

And finally, any time you close your application after your last change but before the post, then you may want to post the change yourself. You'll need to call the ClientDataSet.ApplyUpdates(-1) in the OnDestroy or OnClose event handler of your data module, form, or frame (or whatever container you are using for your ClientDataSet).


Previous: Introduction
 
Next: SQLClientDataSet: The Three-in-One Solution


Introduction SQLClientDataSet: The Three-in-One Solution
Read-Only, Unidirectional Datasets


Return to Get Help with Delphi Page

Return to Main Get Help Page
 
How do I post a new or changed record to a dbExpress dataset when dbExpress provides only unidirectional, read-only datasets?




Use some available components to create solutions that will maintain your dbExpress dataset updates.


Find Out More
• Get the source code for this Solution!

• The DevX Database Development Zone

• Previous 10-Minute Solution: Migrate Your BDE Applications to Linux with dbExpress

• Dr. Bob's Delphi Clinic

TALK BACK
Do you expect dbExpress to replace the Borland Database Engine, especially since Kylix supports only dbExpress? Let us know in the Database Development discussion groups!
 





Sponsored Links