`

TClientDataSet的使用

 
阅读更多

TClientDataSet控件继承自TDataSet,其数据存储文件格式扩展名为 .cds,是基于文件型数据存储和操作的控件。该控件封装了对数据进行操作处理的接口和功能,而本身并不依赖上述几种数据库驱动程序,基本上能满足单机"瘦"数据库应用程序的需要。

1.TClientDataSet的基本属性和方法介绍

  1).FieldDefs: 字段定义列表属性

  开发者可通过单击属性编辑器中该属性编辑按钮,或在该控件上单击右键选择弹出菜单中的"Fields Editor"菜单进行字段编辑。设置完此属性后,实际上就相当于定义了表的结构;如果想装入已有的数据表的结构和数据,可通过单击右键选择弹出菜单中的"Assign Local Data"菜单,从弹出对话框中选取当前窗体中已与数据库连接好的数据集控件名称即可(当前窗体中必须已放置好要套用的数据集控件并打开激活)。

  使用注意:

  对于自定义的字段名表,该属性编辑完后,该控件仍然无法打开。必须右键单击该控件,选择弹出菜单中的"Create DataSet"菜单,让该控件以上述编辑的字段列表为依据,创建数据集后,才能够被激活打开和使用。否则,会出现类似"ClientDataSet1: Missing data provider or data packet."的错误(包括在运行期,运行期可调用该控件的CreateDataSet方法,从而动态定义字段和表)。
2).FileName属性

  说明:数据存储文件的名称。

  因该控件是基于文件型的数据操作控件,因此,必须指定所操作的数据文件名称(默认扩展名称.cds),从而打开和激活该控件,进而进行数据编辑。

  例1:利用此属性打开指定的.cds文件

var
Path: string;
begin
 Path := ExtractFilePath(Application.ExeName); //取得可执行文件路径
 CDataSet1.FileName := Path + 'test.cds';
 CDataSet1.Open;
end;

  3).CreateDataSet方法

  说明:该方法以FieldDefs中的字段名表为结构建立数据集,常用来进行动态定义表。

  例2:动态创建一具有姓名和年龄两个字段的数据集。

//创建字段名表
CDataSet.FieldDefs.Clear;
with CDataSet.FieldDefs.AddFieldDef do
begin
 Name := 'Name';
 Size := 10;
 DataType := ftString;
end;
with CDataSet.FieldDefs.AddFieldDef do
begin
 Name := 'Age';
 DataType := ftInteger;
end;
 //动态创建数据集
 CDataSet.CreateDataSet;
 //激活和打开该数据集
 CDataSet.Open;

4).Open方法

  说明: 打开和激活数据集控件,从而进行数据编辑。

  a. 如果指定了FileName属性,则直接用Open方法即可打开和激活该控件,见例1。

  b. 如果未指定FileName属性,可使用例2方法动态创建和打开数据集,进而操作数据。

5).LoadFromFile和SaveToFile

  说明:从文件中装入表结构和数据以及存储数据到文件。该方法类似于Word中的打开新文件和另存为的功能。

  例3:将数据集的数据存储到指定文件中

CDataSet.SaveToFile('c:\windows\desktop\test.cds');


6).First(到首),Prior(向前),Next(向后),Last(到尾),Edit(编辑),CanCel(取消编辑),Post(保存),Insert(插入记录),Append(添加记录),Delete(删除),Refresh(数据刷新)等数据集常用方法

  说明:当指定了FileName属性时,其Post方法可将数据存入指定的文件中,类似其SaveToFile方法;如果未指定存储文件名,则Post方法只将数据存储在RAM中。其它方法,同一般数据集控件使用方法,略。

7).Filter, Filtered: 过滤筛选属性

  说明:用于筛选指定条件的记录,用法同一般数据集控件,略。

  例4:在已经激活打开的数据集中筛选性别为男性的记录

CDataSet.Close;
CDataSet.Filter := '性别=''' + '男' + '''';
CDataSet.Filtered := True;
CDataSet.Open;


2.使用TClientDataSet控件的应用程序发布的注意事项:

  如前所述,使用TClientDataSet控件的程序发布时不需要任何数据库驱动程序,大大节省了安装文件的大小。但是,在发布程序时别忘了将Windows系统目录下midas.dll(257KB)与应用程序一起发布(运行必须),否则,程序仍然无法正常运行。


三、结束语

  通过使用Delphi中TClientDataSet控件,既实现了应用程序可彻底脱离数据库驱动程序,也实现了常规数据集控件简单易用的特性,为编写"瘦"数据库应用程序提供了一种技术方法和手段。

  上述程序在Pwindows98,Delphi5下测试通过。


TClientDataSet在三层结构中,TClientDataSet的地位是不可估量的,她的使用正确与否,是十分关键的,本文从以下几个方面阐述她的使用,希望对你有所帮助.
1.动态索引
procedure TForm1.DBGrid1TitleClick(Column: TColumn);
begin
if (not column.Field is Tblobfield) then//Tblobfield不能索引,二进制
ClientDataSet1.IndexFieldNames:=column.Field.FieldName;
end;
2.多层结构中主从表的实现
设主表ClientDataSet1.packetrecord为-1,所有记录
设从表ClientDataSet1.packetrecord为0,当前记录
3.Taggregates使用
(1)在字段编辑中add new field类型为aggregates
后设置expression(表达试)
设置active:=true即可
使用dbedit的field为前者即可
(2)使用Aggergates属性add设计表达试
调用
  showmessage(floattostr(ClientDataSet1.Aggregates.Count));
  showmessage(ClientDataSet1.Aggregates.Items[0].Value);


4.在单层数据库中不要BDE
使用ClientDataSet代替table,使用ClientDataSet的loadfilename装入cds
代替table的tablename的db或者dbf
原来的程序改造方法:
加一个ClientDataSet,使用右键assign locate data
后savetofile,再loadfromfile,后删除table
将原连table的datasource设为ClientDataSet
唯一注意的是:要将midas.dll拷到system或者当前目录
5.三层结构的公文包的实现方法
同时设定1:filename(*.cds)2.remote server
6.可以对data赋值(从另一个数据集取值)
ClientDataSet2.Data:=ClientDataSet1.Data;
ClientDataSet2.Open;
或者
ClientDataSet2.CloneCursor(ClientDataSet1,true);
ClientDataSet2.Open;
7.附加数据取得
客户程序向应用服务器请求数据。如果TClientDataSet 的
FetchOnDemand 属性设为True,
客户程序会根据需要自动检索附加的数据包如BLOB字段的值或嵌套表的内容。
否则,
客户程序需要显式地调用GetNextPacket 才能获得这些附加的数据包。
ClientDataSet的packetrecords设置一次取得的记录个数
8.ClientDataSet与服务器端query连接方法
(1)sql内容为空
ClientDataSet1.Close;
ClientDataSet1.CommandText:=edit1.Text;//即sql内容
ClientDataSet1.Open;
对于没有应用服务器设置filter 如:country like 'A%'
filtered=true可实现sql功能
(2)有参数
如服务端query的sql为
select * from animals
where name like :dd
则:客户端ClientDataSet
var
pm:Tparam;
begin
ClientDataSet1.Close;
ClientDataSet1.ProviderName:='DataSetProvider1';
pm:=Tparam.Create(nil);
pm.Name:='dd';
pm.DataType:=ftString;
ClientDataSet1.Params.Clear;
ClientDataSet1.Params.AddParam(pm);
ClientDataSet1.Params.ParamByName('dd').AsString:=edit1.Text ;
ClientDataSet1.Open;
pm.Free;
end;

9.数据的更新管理
(1)savepoint 保存目前为止数据状态,可以恢复到这个状态
var
pp:integer;
begin
pp:=ClientDataSet1.SavePoint;
ClientDataSet1.Edit;
ClientDataSet1.FieldByName('姓名').asstring:='古话';
ClientDataSet1.Post;
table1.Refresh;
end;
恢复点
ClientDataSet1.SavePoint:=pp;
(2)cancel,RevertRecord
取消对当前记录的修改,只适合没有post的,如果post,调用
RevertRecord
(3)cancelupdate
取消对数据库所有的修改
(4)UndoLastChange(boolean),changecount
取消上一次的修改,可以实现连续撤消
参数为true:光标到恢复处
false:光标在当前位置不动
changecount返回修改记录的次数,一个记录修改多次,返回只一次
但UndoLastChange只撤消一次

10.可写的recno
对于Ttable和Tquery的recno是只读的,而TClientDataSet的recno可读可写
ClientDataSet1.recno:=5;是设第五个记录为当前记录
11.数据保存
对于table使用post可更新数据
而ClientDataSet1的post只更新内存数据,要更新服务器数据要使用
ApplyUpdates(MaxErrors: Integer),他有一个参数,是允许发出错误的
次数,-1表示无数次,使用simpleobjectbroker时常设为0,实现自动容错和负载平衡


======================================================

影响ClientDataSet处理速度的一个因素
TClientDataSet是Delphi开发数据库时一个非常好的控件。有很强大的功能。
我常常用ClientDataSet做MemoryDataSet来使用。还可以将ClientDataSet的数据保存为XML,这样就可以做简单的本地数据库使用。还有很多功能就不多说了。在使用ClientDataSet的过程中关于怎样提高处理速度这个问题,我就我个人的一点点体会和大家分享一下。

通常情况下我们一般都是用
...ClientDataSet-->DataSource-->DBComponent
这样的结构,处理数据的时候就直接操作ClientDataSet。但是大多DBComponet都会立即响应ClientDataSet的变化。如果你是向ClientDataSet中插入很多数据时候,DBComponent就要响应几次,而且响应过程根据不同的控件,速度,过程数量都不一样。这样就影响了程序的执行效率。所以在对ClientDataSet处理中,我是用ClientDataSet.DisableControls和ClientDataSet.EnableControls方法:打开和关闭DBComponent与ClientDataSet的数据显示关系。
例如:
ClientDataSet..DisableControls;
...
for I := 0 to 10000 do
begin
ClientDataSet.Append;
...
ClientDataSet.Post;
end;
...
ClientDataSet.EnableControls
...
这样做以后你会发现处理速度比以前没有使用方法的时候有成倍的提高。

ClientDataSet的数据查找。
我所介绍的心得和技巧都是用ClientDataSet来做范例,也可以应用于其他的一些DataSet。废话就不多说了。我们还是先看代码,让后再总结。
1.Scanning 扫描数据查找
这是最简单最直接也是最慢的一种方法,遍历所有数据:
procedure TForm1.ScanBtnClick(Sender: TObject);
var
Found: Boolean;
begin
Found := False;
ClientDataSet1.DisableControls;
Start;
try
ClientDataSet1.First;
while not ClientDataSet1.Eof do
begin
if ClientDataSet1.Fields[FieldListComboBox.ItemIndex].value =
SearchText then
begin
Found := True;
Break;
end;
ClientDataSet1.Next;
end;
Done;
finally
ClientDataSet1.EnableControls;
end;
if Found then ShowMessage(SearchText +
' found at record ' + IntToStr(ClientDataSet1.RecNo))
else
ShowMessage(ScanForEdit.Text + ' not found');
end;

2.Finding 寻找数据
最老,但是最快的查找方式。
使用FindKey/FindNearest来查找一条或多条符合条件的数据,当然待查找的Field必须是一个IndexField。可以看出,这种基于Index的查找速度是非常快的。
procedure TForm1.FindKeyBtnClick(Sender:
TObject);
begin
Start;
if ClientDataSet1.FindKey([SearchText]) then
begin
Done;
StatusBar1.Panels[3].Text := SearchText +
' found at record ' +
IntToStr(ClientDataSet1.RecNo);
end
else
begin
Done;
StatusBar1.Panels[3].Text :=
SearchText + ' not found';
end;
end;

procedure TForm1.FindNearestBtnClick(Sender: TObject);
begin
Start;
ClientDataSet1.FindNearest([SearchText]);
Done;
StatusBar1.Panels[3].Text := 'The nearest match to ' +
SearchText + ' found at record ' +
IntToStr(ClientDataSet1.RecNo);
end

3.Going 定位
GotoKey/GotoNearest 与FindKey/FindNearest基本上没有什么区别。它也是基于Index的查找。唯一的区别就是在于你是怎么定义你的查找了。代码上也有区别:
ClientDataSet1.SetKey;
ClientDataSet1.FieldByName(IndexFieldName).value := SearchText;
ClientDataSet1.GotoKey;
就相当于
ClientDataSet1.FindKey([SearchText]);
要用好这两种基于Index的查找,还需要了解ClientDataSet和Index机制。这里就不详细说明Index机制。一个基本的原则,要有Index,才能查找。

4.Locating 查找数据
2,3两种查找方式都是基于Index的,但是在实际应用中,可能会查找IndexField以外的Field。那我们就可以使用Locate。但是查找速度是没有2,3两种快的。比如:如果你查找一条纪录9000/10000,Locate需要500ms,Scanning需要>2s,FindKey只要10ms(但是当你打开ClientData的时候,建立Index需要1s)。
procedure TForm1.LocateBtnClick(Sender:
TObject);
begin
Start;
if ClientDataSet1.Locate('Field1,Field2..',VarArrayOf['value1,value2..'], []) then
begin
Done;
StatusBar1.Panels[3].Text :=
'Match located at record ' +
IntToStr(ClientDataSet1.RecNo);
end
else
begin
Done;
StatusBar1.Panels[3].Text := 'No match located';
end;
end;


小结:
ClientDataSet提供了好多种查找数据的方法。但是各自有其优缺点。
上面的例子中有Start;和Done,如果你有兴趣,可以加入计时点进行速度测试。
Scanning最简单,但是最慢,因为比较慢,还得使用ClientDataSet.DisableControls和ClientDataSet.EnableControls方法(我在前面一片文章讲过)。
Findkey/FindNearest(GotoKey/GotoNearest)代码多,但是非常快。必须使用Index,不同的是Find需要的Index是必须建立好的,而Goto可以在第一次使用时建立Index。
Locate使用最方便,不需要Index,但是速度没有Find快。

分享到:
评论

相关推荐

    DELPHI数据控件TclientDataSet的详细说明

    DELPHI数据控件TclientDataSet的详细说明 TclientDataSet是DELPHI数据控件中的一种重要组件,它继承自TDataSet,用于多层体系结构的客户端。与TTable、TQuery一样,TClientDataSet也可以用于浏览、编辑、搜索、纠错...

    TClientDataSet用法

    这意味着在客户端应用中使用TClientDataSet时无需安装或配置BDE,而是通过一个名为DBCLIENT.DLL的动态链接库来支持其运行。 在多层架构的应用程序中,客户端通常不直接与数据库进行交互,而是通过中间层(如业务...

    TClientDataSet

    ### TClientDataSet 控件学习知识点详解 #### 一、TClientDataSet 概览 TClientDataSet 是 Delphi 或其他 RAD Studio 系统中一个重要的数据处理控件,它继承自 TDataSet,主要用于本地数据存储和操作。相比于其他...

    Delphi三层开发小技巧:TClientDataSet的Delta妙用

    `TClientDataSet`的`Delta`属性在其中起到了关键作用。`TClientDataSet`是一个非常强大的组件,它不仅可以存储和处理数据,还能记录对数据的修改,这些修改就保存在`Delta`属性中。在三层架构中,通过合理利用`Delta...

    利用delphi中的内存表来制作主从表

    在Delphi中,我们可以通过以下步骤使用TClientDataSet创建主从表: 1. **创建内存表对象**:首先,需要在组件面板上找到TClientDataSet组件,将其拖放到窗体上。对于主从表,你需要创建两个TClientDataSet对象,...

    cds-memleak:TClientDataset内存泄漏

    cds-memleak 完成该项目的目的是揭示Delphi中一个广泛使用的名为TClientDataset的组件中的内存泄漏。动机我工作的公司到处都使用TClientDatasets。 我们已经编写了许多后端工具来支持我们的数据传递系统。 一种这样...

    Delphi主从表自创实例

    接下来,我们可能需要使用TClientDataSet组件,它是Delphi中一种强大的离线数据处理组件,可以处理主从表关系。主表的TClientDataSet通过设置其MasterSource和MasterField属性与从表的TClientDataSet关联。这样,当...

    DELPHI_表格控件DBGridEh史上最全使用资料(101页).rar_DBGridEh_delphi

    通过绑定到数据集组件(如TClientDataSet),DBGridEh可以实时显示和编辑数据库中的数据,支持多种数据类型,包括字符串、数字、日期/时间以及自定义对象。 在功能上,DBGridEh提供了许多高级特性。它支持列的定制...

    delphixe8 uJSONDB

    在本教程中,我们将深入探讨如何将TClientDataSet的数据转换为JSON格式,以及如何将JSON数据恢复到TClientDataSet中,以实现与JSON的无缝对接。 首先,我们需要理解TClientDataSet的基本工作原理。TClientDataSet是...

    delphi不需注册MIDAS.DLL

    能不能使用TClientDataSet又不用MIDAS.DLL呢? 很简单,就是uses一下MidasLib单元! MidasLib单元在Delphi6以及DELPHI的更高版本中才有,是Lib目录下的一个dcu文件。一旦在你的源程序中引用了MidasLib单元,...

    Delphi内存表使用(TdxMemData,TVirtualTable,TFDMemTable)例子.rar

    演示在Delphi上使用内存表存储数据的例子。TdxMemData 属于DevExpressVcl控件,TVirtualTable属于UniDAC控件,TFDMemTable属于FireDAC控件。经过测试证明,TFDMemTable性能最好!

    Delphi/Kylix数据库开发附书源码

    CDSIndex-演示如何在TClientDataSet上创建和使用索引。 RangeFilter-演示如何通过应用范围和过滤器限制TClientDataSet中的数据量。 Search-演示在客户数据集中快速定位给定记录的各种方式。 第4章 EventLog...

    TEXT文本数据读入数据库

    - **提交数据**:一旦`TClientDataSet`填充完毕,使用`TClientDataSet.ApplyUpdates`方法将数据提交到数据库中。 4. **DBGrid显示数据**: - **链接`TDataSource`**:创建`TDataSource`组件,并将其`DataSet`属性...

    Delta 转 Sql语句,包括CDS与TFDMemTable

    TFDMemTable是FireMonkey框架下的一种内存数据表组件,类似于VCL中的TClientDataSet。它允许开发者在内存中创建和管理数据表,支持数据的增删改查操作,同时可以与数据库进行交互。TFDMemTable没有CDS的中间层特性,...

    Delphi Json 存 DataSet (memory)实用代码,Delphi原生TJson

    标题提到的"Delphi Json 存 DataSet (memory)实用代码"是指如何将接收到的JSON数据转换并存储到内存中的DataSet(通常是TClientDataSet或TDataset的子类)中,以便进行进一步的处理或操作。描述中指出,这种做法...

    dbexpress与元数据的Delphi结合实例

    在Delphi中,元数据通常由TClientDataSet组件处理,它可以获取数据库表的结构信息,并在内存中创建一个数据集副本。通过调用TClientDataSet的CreateDataset方法,可以连接到数据库并加载元数据。例如: ```delphi ...

    Delphi中JSon SuperObject 使用数据集与JSON对象互转.docx

    class function TTableJSon.CDSFromJSon(CDS: TClientDataSet; Json: ISuperObject): Boolean; var ColsJson: ISuperObject; begin Result := False; if Json = nil then Exit; CDS.Close; CDS.Data := Null; ...

    Delphi_database.rar_DELPHI_database_delphi例程_数据库 浏览

    例如,常见的组件有TClientDataSet、TDatasource、TDBGrid等,它们分别负责数据的存储、数据源的绑定以及数据的可视化展示。 1. **TClientDataSet**: 这是Delphi中一个非常重要的数据组件,它可以在内存中存储和...

Global site tag (gtag.js) - Google Analytics