The general idea of a client/server application implies that the computation workload is shared between two separate programs, the RDBMS and a client application. Although it is very hard to strike a precise line between the two sides, it is certainly useful to do operations on the client. Most database engines (BDE, as we've seen in this chapter, and ADO, as we'll see in Chapter 16, "ActiveX Data Objects") can manipulate client-side data stored in a cache. Using the ClientDataSet component, you can do the same regardless of the database engine you are using, which makes your program more flexible, particularly if you want to use dbExpress, which doesn't provide a similar feature natively.
A practical example will underline what I mean: Suppose you've written a SQL query to retrieve a rather large dataset, and a user wants to see the same data in a different order. You can certainly run a new query, with the proper order by clause, but this implies sending the same (possibly large) dataset once more from the server to the client. Since the client already has the data in memory, it would be more practical and generally faster to re-sort the data in memory and present the same data to the user with a different ordering.
The ClientDataSet component allows you to do this: Attaching the code to sort the data by assigning a proper field name to the IndexFieldNames property. This is often accomplished when the user clicks the field title in a DBGrid component (firing the OnTitleClick event):
procedure TForm1.DBGrid1TitleClick(Column: TColumn); begin
ClientDataSet1.IndexFieldNames := Column.Field.FieldName; end;
TIP Unlike local databases, a ClientDataSet can have dynamic indexes, as they are computed in memory anyway. The component also supports indexes based on a calculated field, specifically an internally calculated field, a type of field available only for this dataset. Unlike ordinary calculated fields, which are computed every time the record is used, values of internally calculated fields are kept in memory. This is why indexes consider them as plain fields.
Indexing is not all the ClientDataSet has to offer. When you have an index, you can define groups based on it, possibly with multiple levels of grouping. There is even specific support for determining the position of a record within a group (first, last, or middle position). Over groups or entire tables, you can define aggregates; that is, you can compute the sum or average value of a column for the entire table or the current group on-the-fly. The data doesn't need to be posted to a physical server, because these aggregate operations take place in memory. You can even define new aggregate fields, to which you can directly connect data-aware controls. I'll explore these capabilities in the next section.
Another very interesting area of the ClientDataSet component is its ability to handle the updates log, undoing changes, looking at their list before committing them, and so on. I'll explore this next.
The ClientDataSet component supports many features, only some of which are related to the three-tier architecture (covered in Chapter 17). This component represents a database completely mapped in memory and can also be made persistent to a local file. Borland marketing has introduced the name MyBase to describe this feature of the ClientDataSet component, which was formerly called the briefcase model.
The important thing to keep in mind is that all of these features are available to any client/ server and even local applications. The ClientDataSet component, in fact, can get its data from a remote connection, from a local dataset (as you must do with dbExpress), or from a local MyBase file. This is another huge area to explore, so I'll simply show you a couple of examples highlighting key features.
Warning The use of the ClientDataSet component, in each of its incarnations, requires either the deployment of the Midas.dll library or the inclusion in the project of the MidasLib unit (available in compiled format only). The core code of this component, in fact, is not directly part of the library and is not available in source code format. This is unfortunate, as many Delphi developers are accustomed to debugging into the source code and using it as the ultimate reference. It is noteworthy, though, the inclusion in Delphi 6 of the DCU version of the library, obtained from a C-language source code. This allows you to avoid deploying the actual library along with your program.
Was this article helpful?