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. Web版记账本开发记录(六)

    经过今天的学习和实践,终于把这个web版的记账系统给做出来了, 虽然是很简单的一个系统,但是自己花费的时间也着实不少. 今天将大部分功能都实现了,接下来就是完善和美化, 接下来会对不足的地方进行改善, ...

  2. 基于TCAM 的高速路由查找

    摘要 随着路由器接口速率的提高,传统的软件路由查找机制已经不能满足要求.目前常见的硬件解决方案是采用TCAM实现关键词 TCAM,路由查找,最长前缀匹配. 1.引言 路由器转发IP 分组时,转发引擎需 ...

  3. Windows 2003 Server R2 x64 IIS6.0 eWebEditor无法显示的问题

    64位的操作系统安装成功后,一般IIS也是默认的64位的解析,所以将程序放到64位操作系统上的时候,会出现IIS错误,解决方案也非常简单,将64位IIS停止,启动32位的就可以了. 输入以下命令启用 ...

  4. hdu6129 Just Do It!

    多校时找规律做过... 题意,给你一个数列a[1], a[2], a[3], a[4], ... , a[n],操作一次后变为a[1], a[1] ^ a[2], a[1] ^ a[2] ^ a[3] ...

  5. Matlab:高阶常微分三种边界条件的特殊解法(中心差分法,高精度导数边界处理)

    函数文件1: function b=F(f,x0,h,N) % b(1,1)=x0(1)-h*x0(2)-u(1); % b(2,1)=x0(2)+h*x0(1)^2-u(2)-h*f; b=zero ...

  6. 数据结构与算法之PHP排序算法(归并排序)

    一.基本思想 归并排序算法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,使每个子序列有序,再将已有序的子序列合并,得到完全有序的序列.该算法是采用分治法(Divid ...

  7. coursera-斯坦福-机器学习-吴恩达-笔记week4

    1 神经网络的提出 线性回归和逻辑回归能很好的解决特征变量较少的问题,但对于变量数量增加的复杂非线性问题,单纯增加二次项和三次项等特征项的方法计算代价太高. 2 神经网络算法 2.1 神经元 模拟神经 ...

  8. String.valueOf() ,其他类型转为字符型

    1. 由 基本数据型态转换成 String String 类别中已经提供了将基本数据型态转换成 String 的 static 方法 也就是 String.valueOf() 这个参数多载的方法 有下 ...

  9. python笔记9-字符串操作

    1.定义字符串 字符串有下标从0开始,用[]可以来取下标 2.字符串读取 字符串可以使用循环for,每次取一个取出,循环对象的每个元素 3.字符串修改-字符串不可修改 字符串是不可变变量,一旦定义就不 ...

  10. DisplayLink 安装错误

    根据 在官网论坛上的反馈结果,程序自己有验证数字签名,数字签名验证不通过,即如上图所示.可能的原因:病毒:下载不完全:证书链出问题