TField对象的SetText和GetText事件处理函数

使用TField对象的SetText和GetText事件处理函数可方便的解决字段的代码与代码所对应值的显示问题

TSimpleDataset/TClientDataset对象的Aggregation

使用TDataset对象的Aggregate属性可以来计算客户端数据集中数据的总计数值、平均值或是计算最大值和最小值。

使用TBookMark来标记记录书签, 访问数据集中的数据

通过使用TBookMark以及TDataset对象的 BookMark 属性, 要以为当前的纪录设置书签,

var

bk:TBookMark;

begin

bk:=ds.GetBookMark; //设置书签

....

ds.GoToBookMark(bk);//回到原来的纪录

ds.FreeBookMark(bk);//释放内存

end;

Locate 与 Lookup 区别:

Locate找到查寻的数据后,它会把目前的记录位置移动到找到的这笔数据上

Lookup找到查寻的数据后,它会回传找到的数据的特定字段数值,却不会移动目前的记录位置。

Lookup方法的第三个参数则是指定当Lookup找到欲查寻的数据之后,要回传这笔数据的那些字段数值。如果开发人员想要Lookup回传多个字段数值,那么每一个字段也是以分号分隔。

至于Lookup方法回传的数值则是第三个字段指定的字段数值,如果Lookup回传多个字段的话,那么这个回传数值就是一个Variant数组,每一个回传的字段便储存在这个Variant数组的元素之中。

例:

ClientDataSet使用心得和技巧

影响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 扫描数据查找

这是最简单最直接也是最慢的一种方法,遍历所有数据:

  1. procedure TForm1.ScanBtnClick(Sender: TObject);
  2. var
  3. Found: Boolean;
  4. begin
  5. Found := False;
  6. ClientDataSet1.DisableControls;
  7. Start;
  8. try
  9. ClientDataSet1.First;
  10. while not ClientDataSet1.Eof do
  11. begin
  12. if ClientDataSet1.Fields[FieldListComboBox.ItemIndex].value = SearchText then
  13. begin
  14. Found := True;
  15. Break;
  16. end;
  17. ClientDataSet1.Next;
  18. end;
  19. Done;
  20. finally
  21. ClientDataSet1.EnableControls;
  22. end;
  23. if Found then
  24. ShowMessage(SearchText + ' found at record ' + IntToStr(ClientDataSet1.RecNo))
  25. else
  26. ShowMessage(ScanForEdit.Text + ' not found');
  27. end;

2.Finding 寻找数据

最老,但是最快的查找方式。

使用FindKey/FindNearest来查找一条或多条符合条件的数据,当然待查找的Field必须是一个IndexField。可以看出,这种基于Index的查找速度是非常快的。

  1. procedure TForm1.FindKeyBtnClick(Sender: TObject);
  2. begin
  3. Start;
  4. if ClientDataSet1.FindKey([SearchText]) then
  5. begin
  6. Done;
  7. StatusBar1.Panels[3].Text := SearchText +  ' found at record ' +  IntToStr(ClientDataSet1.RecNo);
  8. end
  9. else
  10. begin
  11. Done;
  12. StatusBar1.Panels[3].Text := SearchText + ' not found';
  13. end;
  14. end;
  15. procedure TForm1.FindNearestBtnClick(Sender: TObject);
  16. begin
  17. Start;
  18. ClientDataSet1.FindNearest([SearchText]);
  19. Done;
  20. StatusBar1.Panels[3].Text := 'The nearest match to ' +  SearchText + ' found at record ' + IntToStr(ClientDataSet1.RecNo);
  21. 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快。

var

sFields : String;

vResult : Variant;

iCount : Integer;

begin

vResult := ds.Lookup('fieldnameA, fieldnameB' , VarArrayCreate([ValueA, ValueB], varVariant), 'fieldname1, fieldname2');

if (VarIsArray(vResult)) then

begin

sFields := '';

for iCount := VarArrayLowBound(vResult, 1) to VarArrayHighBound(vResult,  1) do

begin

sFields := sFields + ';' + vResult[iCount];

end;

end

else

edtReturn.Text := vResult;

end;

一些使用 DevExpress 时的小心得

1. 设置 DataController.Filter.AutoDataSetFilter=True 可以使过滤器直接影响后台数据集。

2. 关于cxFormatController的一些用法。当修改了系统默认数据格式定义时,cxFormatController可通过方法 GetFormats 与 NotifyListeners 来实现刷新。

例:

CurrencyString := '元';

SysUtils.CurrencyFormat := 3;

SysUtils.CurrencyDecimals := 4;

cxFormatController.GetFormats;

cxFormatController.NotifyListeners;

3.更新当前所选行中某列的值,可以按以下方法实现,

Column.EditValue := AValue。如可使用 Record.Values[AIndex] := AValue, 并不能直接更新行中指定值所对应的数据集中的值。通过 Column.EditValue 刚可以实现。

TDatasetProvider.UpdateMode属性;

upWhereAll   限制最严,但可以最大程度地保证记录的一致性。如果两个用户编辑同一条记录,第一个用户能够更新记录,而第二个用户将会收到“另一个用户已经修改了这条记录”的报错信息。如果希望改进执行这种检查的字段,可以去掉相应的TField.ProviderFlags属性中的pfInWhere项。

upWhereChanged   实际上允许两个用户同时编辑一条记录;在两个用户编辑同一条记录的不同字段时,不会检查出冲突。例如,如果用户A修改Address字段并更新了记录,那么用户B仍然能够修改BirthDate字段并成功地更新记录。

upWhereKeyOnly   限制最宽。只要是记录存在于数据库中,每个用户都可以进行修改并更新。这样,后面的修改总是覆盖前面的修改。

系统默认的是upWhereAll,请修改为你认为合适的模式!

ADO 中处理多个返回结果集

在使用 SQL 语句时,常常会有多个结果集被返回的情况,比如 EXEC sp_helpconstraint [TableName] 就返回了两个结果集。如果我们需要处理多个结果集时。可用ADO的 NextRecordSet 方法。用法如下:

var

R: integer

begin

with ADOQuery do

begin

Close;

SQL.Text := 'EXEC sp_helpconstraint ' + ableName;

Open;

R := 0;

Recordset := NextRecordSet(R);

{do something }

end

在三层结构中,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. delphi中的ClientDataSet组件的open和Execute方法各自在什么情况下用?

    ClientDataSet组件本来是给midas用的,也是所谓的borland的三层数据技术,使用这个控件必须发行midas.dll挺麻烦的 open是通过应用的SQL语句为SELECTexecute ...

  2. 捕获ClientDataSet.ApplyUpdates和SocketConnection异常

    核心提示:如何捕获ClientDataSet.ApplyUpdates的错误,不用ReconcileError... var cdsEmp:TClientDataSet; //保存 procedure ...

  3. clientdataset<---->json

    现在,DATASNAP倾向于使用JSON作为统一的数据序列格式,以期达到跨平台的效果.于是使用JSON便成为热点. unit uJSONDB;   interface uses SysUtils, C ...

  4. ClientDataSet应用

    最近维护一个项目,里面用到ClientDataSet,由于之前接触ClientDataSet比较少,所以这个星期补了一下关于ClientDataSet的知识,并在此记录下我所了解到的并应用到实际项目中 ...

  5. ClientDataSet使用locate或Filter定位到字段为空值的记录

    场景,程序想检查是否存在某个字段的值是空的,如果存在,则不允许增加记录,否则允许增加记录. 解决这个问题,我一开始用了两种错误的方法 if not clientdataset.locate('AFie ...

  6. Delphi ClientDataSet 主从结构 BUG

    使用ADO控件 .ClientDataSet .增加了从表与主表的关连字段 SheetID,别的设置全为默认.如图1所示 图1 ======= 问题 BUG: 打开主表与从表,先不对主表进行任何操作. ...

  7. DataSnap ClientdataSet 三层中主从表的操作

    非原创  摘自:http://hi.baidu.com/yagzh2000/blog/item/fc69df2cb9845de78b139946.html三层中主从表的操作(删除.新增.修改)一定要在 ...

  8. clientdataset.open 报错 Name not unique in this context

    clientdataset.open 报错  Name not unique in this context clientdataset有一些自定义字段,clientdataset绑定了adoquer ...

  9. ClientDataSet 心得

    1.   与TTable.TQuery一样,TClientDataSet也是从TDataSet继承下来的,它通常用于多层体系结构的客户端.很多数据库应用程序都用了BDE,BDE往往给发布带来很大的不便 ...

随机推荐

  1. [JavaScript-Function] Function Invocation/Call(函数调用) 以及call() and apply() 方法

    介绍:JS函数中的代码会被函数被invoke(调用)时执行. 函数被定义时代码不执行, 函数调用时函数内的代码会被执行. 常用的term是 call a function 而不是 invoke a f ...

  2. python-html基础操作

    介绍: HTML  是网页内容的载体.包括文字,图片,信息等用户浏览的信息CSS   样式是改变内容外观表现.像字体,颜色,背景,边框等JavaScript   是实现网页上的特效效果.如鼠标滑过背景 ...

  3. pytorch构建自己的数据集

    现在需要在json文件里面读取图片的URL和label,这里面可能会出现某些URL地址无效的情况. python读取json文件 此处只需要将json文件里面的内容读取出来就可以了 with open ...

  4. tensorflow中命名空间、变量命名的问题

    1.简介 对比分析tf.Variable / tf.get_variable | tf.name_scope / tf.variable_scope的异同 2.说明 tf.Variable创建变量:t ...

  5. 【CUDA】Win10 + VS2017新 CUDA 项目配置

    一.新建项目 打开VS2017 → 新建项目 → Win32控制台应用程序 → “空项目”打钩 二.调整配置管理器平台类型 右键项目 → 属性 → 配置管理器 → 全改为“x64” 三.配置生成属性 ...

  6. Kotlin(一)

    Kotlin(一) 写在前面: 参考资料: <Kotlin官方文档><Kotlin for Android 开源中文版> 准备工作: Android-Studio2.x:添加K ...

  7. centos6升级python

    CentOS 6中,默认安装了Python 2.6.而pip,jupyter这样的常用工具是不支持Python 2.6的.为了使用这些工具,就必须将Python 2.6升级到Python 2.7以上的 ...

  8. VirtualBox fedora29 安装

    目录 准备工作 VirtualBox安装 fedora安装 快捷键定义 准备工作 平台配置 win10 64位 内存 8G 硬盘 1T 下载地址 VirtualBox 5.2.22:https://w ...

  9. Shell 变量替换及测试

    声明:$ 后面跟linux可执行命令 一.变量替换                   语法                      说明 ${变量名#匹配规则} 从变量的开头进行规则匹配,将符合最 ...

  10. makefile简单学习

    前言 在C语言中,我们需要将源代码生成可执行的程序.这里面其实要经过非常多的步骤.参看下图: 这中间主要通过make命令,读取一种名为“makefile”或“Makefile”的文件来实现软件的自动化 ...