影响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快

在三层结构中,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 用法相关推荐

  1. ClientDataSet的用法(转)

    ClientDataSet的用法(转) TClientDataSet控件继承自TDataSet,其数据存储文件格式扩展名为 .cds,是基于文件型数据存储和操作的控件.该控件封装了对数据进行操作处理的 ...

  2. Delphi:ClientDataset+TDataSetProvider的数据保存问题

    看到一篇介绍ClientDataSet和TDataSetProvider,非常精彩,特此保存. ==================================================== ...

  3. ClientDataSet建立索引和排序

    可用ClientDataSet.AddIndex或ClientDataSet1.IndexDefs.AddIndexDef建立索引. AddIndex( const Name:string;     ...

  4. c语言中external,static关键字用法

    static用法: 在C中,static主要定义全局静态变量.定义局部静态变量.定义静态函数. 1.定义全局静态变量:在全局变量前面加上关键字static,该全局变量变成了全局静态变量.全局静态变量有 ...

  5. Pandas_transform的用法

    先来看一个实例问题. 如下销售数据中展现了三笔订单,每笔订单买了多种商品,求每种商品销售额占该笔订单总金额的比例.例如第一条数据的最终结果为:235.83 / (235.83+232.32+107.9 ...

  6. Python中yield和yield from的用法

    yield 后面接的是 future 对象 调用方 委托生成器 yield from 直接给出循环后的结果 yield from 委托者和子生成器直接通信 yield from 直接处理stopIte ...

  7. pytorch学习 中 torch.squeeze() 和torch.unsqueeze()的用法

    squeeze的用法主要就是对数据的维度进行压缩或者解压. 先看torch.squeeze() 这个函数主要对数据的维度进行压缩,去掉维数为1的的维度,比如是一行或者一列这种,一个一行三列(1,3)的 ...

  8. python yield 和 yield from用法总结

    #例1. 简单输出斐波那契數列前 N 个数 #缺点:该函数可复用性较差,因为 fab 函数返回 None,其他函数无法获得该函数生成的数列 #要提高 fab 函数的可复用性,最好不要直接打印出数列,而 ...

  9. tf.nn.embedding_lookup()的用法

    函数: tf.nn.embedding_lookup( params, ids, partition_strategy='mod', name=None, validate_indices=True, ...

最新文章

  1. android studio同步代码块,Android Studio快捷键大全
  2. linux下VNC配置详解
  3. iis 服务器出现server too busy!
  4. CF-825 G.Tree Queries(DFS)
  5. leetcode84. 柱状图中最大的矩形
  6. php的ddd,在MVC框架中实现DDD – PHP
  7. 数据结构与算法--图的表示与常用算法
  8. 处于风口浪尖的区块链和人工智能,联手在这些领域落地有声
  9. shell 的source指令和.指令
  10. python判断字符串包含中文_查询字符串中是否包含中文字符(Python实现)
  11. TOGAF 知识点整理
  12. 康托尔连续统假设(CH)不成立
  13. Qt串口通信实时曲线上位机源代码
  14. 2007年IT产业回顾:划时代的一年 一个变革的时代
  15. 在c语言中pwm的作用,详细注解的PWM c程序初学者适用
  16. php把字符串做为代码执行的函数eval
  17. 中国十大虚拟主机服务商
  18. php 实现倒计时-将秒数转换为时间(天、小时、分、秒)
  19. 电压放大器原理(电压放大器适用于什么场合使用)
  20. C - 数字三角形问题

热门文章

  1. Ubuntu 32下Android NDK+NEON的配置过程及简单使用举例
  2. 【Qt】error: undefined reference to `vtable for MainWindow‘
  3. c语言字符串机考题,2016全国计算机二级《C语言》机考试题及答案
  4. vue 引入的方法 用在template_?【有手就行】轻松打造属于自己的Vue工程化脚手架工具...
  5. java nextline_Java编程语言基础的9根支柱
  6. python编写脚本方法_【Python】教你一步步编写banner获取脚本
  7. Java项目:家庭财务管理系统(java+Springboot+ssm+mysql+maven)
  8. php 缓存模块,PHP缓存之模块缓存(APC)_PHP教程
  9. mysql删除原则_MySQL数据库的增删选查
  10. python技术晨讲_python系列教程14