Dataset Enumerator Reloaded

A couple of years ago I wrote a two-part article about a dataset enumerator: A Magical Gathering – Part 1 and Part 2. Well, things evolved a bit since then and I wondered how one would implement something similar given the current features of Delphi. Actually I am following here a suggestion from commenter Alan Clark.

The enumerator is implemented quite similar to the original version using a class helper, which makes it available for all TDataSet descendants. The variant part is completely replaced with a generic approach allowing type safety as well as code completion.

Let’s have a look at the public section of TDataSetHelper:

The first thing to mention is that the enumerator is no longer exposed by the dataset directly. Instead we now have two overloaded functions named Records returning the same generic interface IRecords<T>.

As you see, this interface has no other task than to expose the actual enumerator.  The reason is to make use of reference counting to control the lifetime of the inner objects. I also found no other way to get a generic enumerator.

Back to the class helper we notice that one of these functions has a generic constraint record, while the other one has a similar constraint for class, with the addition of taking a parameter with that class type. A similar approach is used for the method pairs GetCurrentRec/SetCurrentRec and LoadInstanceFromCurrent/StoreInstanceToCurrent. Besides the enumerator support the class helper obviously allows loading and storing the current dataset record into/from a record or class instance of the given type.

Before diving too much into the implementation details let’s have a look at how this can be used in our code. The example that comes with the sources contains a ClientDataset made up from the employee.xml file which can be found in Delphis samples/data folder. In the code we declare a record that matches the fields in that dataset.

This is the code using the enumerator to fill a memo with some information about our employees.

Now a use case for GetCurrentRec:

The TCustomer class is bound to the customer.xml table and is a bit more sophisticated:

There are some attributes controlling the mapping of the properties and fields to the dataset fields. Properties Address1 and Address2 are mapped to the dataset fields Addr1 and Addr2. Property CustNo is not mapped to any field as it is of type integer while the corresponding table field is of type float. Instead we map FCustNo to that dataset field which happens to have the proper type for that. Last FZipCode is mapped to dataset field Zip. The other properties are automatically mapped to their corresponding dataset fields.

The enumerator example for TCustomer needs an instance of that class to work with.

Loading and saving data is done in a similar way.

The source code of TDatasetHelper with a small example can be downloaded here: Dataset Enumerator .

Author: Uwe Raabe

Addicted to Pascal/Delphi since the late 70's

6 thoughts on “Dataset Enumerator Reloaded”

  1. Thank you Uwe Raabe for the beauty library.
    It does not compile under Delphi XE7.
    Could you check the issue?

    1. That is a limitation of XE7 probably related to RSP-10068 which was fixed in XE8.
      You may need to flatten the nested types to make it compile with XE7 and below.

  2. Thank you very much. We had similar functionality but not implemented in such an elegant way. This should be built into TDataset.

Comments are closed.