Вы находитесь на странице: 1из 6

Defining a ClientDataSet's Structure Using FieldDefs http://dn.codegear.

com/print/28959

Defining a ClientDataSet's Structure Using


FieldDefs
By: Cary Jensen

Abstract: When creating a ClientDataSet's memory store on-the-fly, you must explicitly define the
structure of your table. This article shows you how to do it at both runtime and design-time using
FieldDefs.
The ClientDataSet is an in-memory data store that lets you to view, edit, and navigate data. Because
these operations are performed on data held in memory, they tend to be performed very quickly.
This is the second article in a series designed to detail the use of the ClientDatSet. In the last
installment, I provided you with a basic overview of ClientDataSet, with particular attention paid to
how a ClientDataSet gets its data from a DataSetProvider. You use a ClientDataSet with a
DataSetProvider when you obtain your data through a remote database management system (RDBMS)
or a local database engine, such as the Borland Database Engine (BDE). Instead of using a
DataSetProvider, it is possible to load and save the data held by a ClientDataSet from the local file
system. Borland calls this mechanism MyBase.
As you learned in the preceding article in this series, a ClientDataSet loaded through a
DataSetProvider get its metadata, the data that defines the fields of the dataset (commonly referred to
as a table's structure), through the DataSetProvider. This metadata is produced by the
DataSetProvider, based on the DataSet to which it points.
When a ClientDataSet gets its data from a local file using MyBase, the metadata is read from this file.
However, neither mechanism is available when you create the in-memory dataset on-the-fly, at
runtime. In these situations, it is necessary for you to explicitly define the structure of the
ClientDataSet. Defining this metadata can be done either at design-time or at runtime. Once the
metadata is defined, you create the in-memory dataset by calling the ClientDataSet's CreateDataSet
method, or by using the ClientDataSet's component editor in the designer.
There are two ways to define the metadata of a ClientDataset. You can use the FieldDefs property of
the ClientDataSet, or you can create TFields and associate them with the ClientDataSet. Creating the
metadata definitions using FieldDefs is the most common. However, FieldDefs does not permit you to
create virtual fields, such as calculated or aggregate fields. Similarly, using FieldDefs does not allow
you to easily create nested datasets. Nested datasets represent one-to-many (sometimes called
master-detail or parent-child) associations in your data. In this article you will learn how to use
FieldDefs. The next article in this series will discuss the use of TFields to define the structure of a
ClientDataSet.

Defining a Table's Structure Using FieldDefs


You can configure FieldDefs either at design time or at runtime. To define the structure of a client
dataset at design time, you use the FieldDefs collection editor to create individual FieldDef instances.
You then use the Object Inspector to configure each FieldDef, defining the field name, data type, size,
or precision, among other options. At runtime, you define your FieldDef objects by calling the
FieldDefs AddFieldDef or Add methods. This section begins by demonstrating how to create your
ClientDataSet's structure at design-time. Defining the table structure at runtime is shown later in this
article.

Creating FieldDefs at Design-time

You create FieldDefs at design-time using the FieldDefs collection editor. To display this collection
editor, select the FieldDefs property of a ClientDataSet in the Object Inspector and click the displayed
ellipsis button. The FieldDefs collection editor is shown in the following figure.

1 of 6 20.11.2008 17:18
Defining a ClientDataSet's Structure Using FieldDefs http://dn.codegear.com/print/28959

Using the FieldDefs collection editor, click the Add New button (or press Ins) once for each field that
you want to include in your ClientDataSet. Each click of the Add New button (or press of Ins) will
create a new FieldDef instance, which will be displayed in the collection editor. For example, if you add
five new FieldDefs to the FieldDefs collection editor, it will look something like that shown in the
following figure.

You must configure each FieldDef that is added to the FieldDefs collection editor before the dataset can
be created. To configure a FieldDef, select the FieldDef you want to configure in the collection editor or
the Object TreeView, and then use the Object Inspector to set its properties. The following is how the
Object Inspector looks when a FieldDef is selected. (Notice that the Attributes property has been
expanded to display its subproperties.)

At a minimum, you must set the DataType property of each FieldDef. You will also want to set the
Name property. The Name property defines the name of the corresponding field that will be created.
Other properties you will often set include the Size property, which you define for String, BCD (binary
coded decimal), byte, and VarByte fields, and the precision property for BCD fields. Similarly, if a
particular field requires a value before the record to which it is associated can be posted, set the
faRequired subproperty of the Attributes property to True. For information on the other properties of
the TFieldDef class, see the online help.
After setting the necessary properties of each FieldDef, you can create the ClientDataSet. This can be
done either at design-time or runtime. To create the ClientDataSet at design-time, right-click the

2 of 6 20.11.2008 17:18
Defining a ClientDataSet's Structure Using FieldDefs http://dn.codegear.com/print/28959

ClientDataSet and select Create DataSet, as shown in the following figure.

Creating the dataset at design-time creates an in-memory table, but does not actually create a
physical file on disk. You save a physical file by right-clicking the ClientDataSet and selecting one of
the save options, such as Save to MyBase Xml table or Save to binary MyBase file.

If you create your physical file at design-time, you will then likely need to deploy that file, along with
any other required files. As a result, many ClientDataSet users create the ClientDataSet at runtime.
As mentioned earlier in this article, this task is performed by calling the ClientDataSet's
CreateDataSet method. For example, consider the following event handler, which might be associated
with the OnCreate event handler of the form to which it is associated.

procedure TForm1.FormCreate(Sender: TObject);


const
DataFile = 'mydata.xml';
begin
ClientDataSet1.FileName := ExtractFilePath(Application.ExeName) + DataFile;
if FileExists(ClientDataSet1.FileName) then

3 of 6 20.11.2008 17:18
Defining a ClientDataSet's Structure Using FieldDefs http://dn.codegear.com/print/28959

ClientDataSet1.Open
else
ClientDataSet1.CreateDataSet;
end;

This code begins by defining the FileName property of the ClientDataSet, pointing to a file named
mydata.xml in the application directory. Next, it tests to see if this file already exists. If it does, it
opens the ClientDataSet, loading the specified file's metadata and data into memory. If the file does
not exist, it is created through a call to CreateDataSet. When CreateDataSet is called, the in-memory
structure is created based on the FieldDefs property of the ClientDataSet.

Creating FieldDefs at Runtime


Being able to create FieldDefs at design-time is an important feature, in that the Object Inspector
provides you with assistance in defining the various properties of each FieldDef you add. However,
there may be times when you do not know the structure of the dataset that you need until runtime. In
those cases, you must define the FieldDefs property at runtime.
As mentioned earlier in this article, there are two methods that you can use to configure the FieldDefs
property at runtime. The easiest technique is to use the Add method of the TFieldDefs class. The
following is the syntax of Add:

procedure Add(const Name: String; DataType: TFieldType;


Size: Integer = 0; Required: Boolean = False);

This method has two required parameters and two optional parameters. The first parameter is the
name of the FieldDef and the second is its type. If you need to set the Size property, as is the case
with fields of type ftString and ftBCD, set the Size property to the size of the field. For required fields,
set the fourth property to a Boolean True.
The following code sample creates an in-memory table with five fields.

procedure TForm1.FormCreate(Sender: TObject);


const
DataFile = 'mydata.xml';
begin
ClientDataSet2.FileName :=
ExtractFilePath(Application.ExeName) + DataFile;
if FileExists(ClientDataSet2.FileName) then
ClientDataSet2.Open
else
begin
with ClientDataSet2.FieldDefs do
begin
Clear;
Add('ID',ftInteger, 0, True);
Add('First Name',ftString, 20);
Add('Last Name',ftString, 25);
Add('Date of Birth',ftDate);
Add('Active',ftBoolean);
end; //with ClientDataSet2.FieldDefs
ClientDataSet2.CreateDataSet;
end; //else
end;

Like the previous code listing, this code begins by defining the name of the data file, and then testing
whether or not it already exists. When it does not exist, the Add method of the FieldDefs property is
used to define the table structure, after which the in-memory dataset is created using the
CreateDataSet method.
If you consider how the Object Inspector looks when an individual FieldDef is selected in the FieldDefs
collection editor, you will notice that the Add method is rather limited. Specifically, using the Add
method you cannot create hidden fields, readonly fields, or BCD fields where you define precision. For
these more complicated types of FieldDef definitions, you will need to use the AddFieldDef method of
the FieldDefs property. The following is the syntax of AddFieldDef:

4 of 6 20.11.2008 17:18
Defining a ClientDataSet's Structure Using FieldDefs http://dn.codegear.com/print/28959

function AddFieldDef: TFieldDef;

As you can see from this syntax, this method returns a TFieldDef instance. Set the properties of this
instance to configure the FieldDef. The following code sample shows you how to do this.

procedure TForm1.FormCreate(Sender: TObject);


const
DataFile = 'mydata.xml';
begin
ClientDataSet2.FileName :=
ExtractFilePath(Application.ExeName) + DataFile;
if FileExists(ClientDataSet2.FileName) then
ClientDataSet2.Open
else
begin
with ClientDataSet2.FieldDefs do
begin
Clear;
with AddFieldDef do
begin
Name := 'ID';
DataType := ftInteger;
end; //with AddFieldDef do
with AddFieldDef do
begin
Name := 'First Name';
DataType := ftString;
Size := 20;
end; //with AddFieldDef do
with AddFieldDef do
begin
Name := 'Last Name';
DataType := ftString;
Size := 25;
end; //with AddFieldDef do
with AddFieldDef do
begin
Name := 'Date of Birth';
DataType := ftDate;
end; //with AddFieldDef do
with AddFieldDef do
begin
Name := 'Active';
DataType := ftBoolean;
end; //with AddFieldDef do
end; //with ClientDataSet2.FieldDefs
ClientDataSet2.CreateDataSet;
end; //else
end;

Saving Data
If you have assigned a file name to the FileName property of a ClientDataSet whose in-memory table
you create using CreateDataSet, and post at least one new record to the dataset, a physical file will be
written to disk when you close or destroy the ClientDataSet. This happens automatically. Alternative,
you can call the SaveToFile method of the ClientDataSet to explicitly save your data to a physical file.
The following is the syntax of SaveToFile

procedure SaveToFile(const FileName: string = '';


Format TDataPacketFormat=dfBinary);

As you can see, both of the parameters of this method are optional. If you omit the first parameter,
the ClientDataSet saves to a file whose name is assigned to the FileName property. If you omit the
second parameter, the type of file that is written to disk will depend on the file extension of the file to
which you are saving the data. If the extension is XML, an XML MyBase file is created. Otherwise, a
binary MyBase file is written. You can override this behavior by specifying the type of file you want to
write. If you pass dfBinary as the second parameter, a binary MyBase file is created. To create an XML
MyBase file when the file extension of the file name is not XML, use dfXML.

5 of 6 20.11.2008 17:18
Defining a ClientDataSet's Structure Using FieldDefs http://dn.codegear.com/print/28959

On more than one occasion I have noticed that the XML MyBase file is not written to disk correctly if
you do not explicitly call SaveToFile. Therefore, even though a ClientDataSet can save its data
automatically, I make a habit of explicitly calling SaveToFile before closing or destroying a
ClientDataSet.

An Example
An example application that demonstrates the use of the FieldDefs methods AddFieldDefs and Add can
be downloaded from Code Central. The following is how the main form of this application looks after
File | Create or Load is selected from the main menu.

About the Author


Cary Jensen is President of Jensen Data Systems, Inc., a Texas-based training and consulting company
that won the 2002 Delphi Informant Magazine Readers Choice award for Best Training. He is the
author and presenter for Delphi Developer Days (www.DelphiDeveloperDays.com), an information-
packed Delphi seminar series that tours North America and Europe. Cary is also an award-winning,
best-selling co-author of eighteen books, including Building Kylix Applications (2001,
Osborne/McGraw-Hill), Oracle JDeveloper (1999, Oracle Press), JBuilder Essentials (1998,
Osborne/McGraw-Hill), and Delphi In Depth (1996, Osborne/McGraw-Hill). For information about
onsite training and consulting you can contact Cary at cjensen@jensendatasystems.com, or visit his
Web site at www.JensenDataSystems.com.
Click here for a listing of upcoming seminars, workshops, and conferences where Cary Jensen is
presenting.
Copyright ) 2002 Cary Jensen, Jensen Data Systems, Inc.
ALL RIGHTS RESERVED. NO PART OF THIS DOCUMENT CAN BE COPIED IN ANY FORM WITHOUT THE
EXPRESS, WRITTEN CONSENT OF THE AUTHOR.

Published on: 8/1/2002 12:04:54 PM


Server Response from: BDN9A

Copyright© 1994 - 2008 Embarcadero Technologies, Inc. All rights reserved.

6 of 6 20.11.2008 17:18

Вам также может понравиться