Delphi 三层 TClientDataSet(2)

delphi Midas SQLServer的自增字段的处理
1.新增时,表中有自增字段,但是不希望用Refresh,直接ApplyUpdates直接看见自增字段的值
在DataSetProvider.AfterUpdateRecord写如下代码

DataSetProvider.Options.poPropogateChanges:=True;

procedure TForm1.DataSetProvider1AfterUpdateRecord(Sender: TObject;
  SourceDS: TDataSet; DeltaDS: TCustomClientDataSet;
  UpdateKind: TUpdateKind);
begin
//DstId TADODataset
//FId 为自增字段
  if   UpdateKind=ukInsert then
  begin
  DstId.CommandText:='select  @@Identity as FId ';
  DstId.Open;
  DeltaDS.FieldByName('FId').ReadOnly:=False;
  DeltaDS.FieldByName('FId').NewValue:=DstId.FieldByName('FId').AsInteger ;
  DstId.Close;
  end;

end;

2.
新增时,从表的关联字段与主表的自增字段同步更新
procedure TProducts.DataSetProvider1BeforeUpdateRecord(Sender: TObject;SourceDS: TDataSet; DeltaDS: TCustomClientDataSet;UpdateKind: TUpdateKind; var Applied: Boolean);
begin
//DstProduct为从表的Name
//CategoryID是从表的对于主表的字增自段的关联字段
// qryIdentity是TADOQuery qryIdentity.SQL:='select @@identity'

  if (UpdateKind = ukInsert) and
  (SourceDS = DstProduct) and
  (DeltaDS.FieldByName('CategoryID').Value =  Unassigned)   ) then
  begin
    if DeltaDS.BOF then
    begin
      qryIdentity.Close;
      qryIdentity.Open;
    end;
    DeltaDS.FieldByName('CategoryID').NewValue := qryIdentity.Fields[0].Value;
  end;
end;


     Delphi做为一个快速应用开发工具,深受程序员的喜爱。

     其强大的组件功能,让程序员能够轻松、高效地完成常见的界面开发、数据库应用等功能。然而,帮助的相对缺乏,使得许多组件的功能并不为人们正确地使用,究其原因,仍然是认识上的问题。对于MIDAS开发中的核心部件,TClientDataSet和TDataSetProvider,由于资料的缺乏,人们在网上大多谈论的是李维的书籍内容。我有幸在BDN上见到了Cary Jensen的Professional Developer系列文章,详细阐述了DELPHI的数据库开发技术。现节选出其中的ClientDataSet部分,与大家共同分享。

ClientDataSet是一个功能强大的类,通过在内存中模拟表格,实现了其它数据集组件所不具备的强大功能。以往只在Delphi和C++ Builder企业版中才提供这个组件,如今,Borland的全部产品(包括最新的Kylix)都集成了TClientDataSet组件。

TClientDataSet从类的继承关系上来看,是TDataSet这个抽象类的子类,所以我们可以在TDataSet这个抽象层次上对其进行我们熟悉的操作,比如导航、排序、过滤、编辑

要注意的是,TClientDataSet使用了一种全新的技术,它将所有的数据均放在内存中,所以TClientDataSet是个只存在内存中的“虚拟表”,因此对数据库的操作是非常快的。在PIII 850,512MB的机器上对十万条记录进行建索引的操作,花费的时间少于半分钟。

与一般的数据集组件不同,TClientDataSet使用的技术比较特别,本着高速度、低存储需求的原则,TClientDataSet的内部使用了两个数据存储源。

第一个是其Data属性,这是当前内存数据的视图,反映了所有的数据改变。如果用户从数据中删除一条记录,则此记录将从Data中消失,相应地,加入一条新记录后,此记录便存在Data属性中了

另一个数据源是Delta属性,故名思义,即增量的意思,这个属性反映了对数据的改变。

无论是向Data属性新增还是删除记录,都会在Delta中记录下来,如果是修改了Data中的记录,则会在Delta保存两条相应的记录,一条是原始记录,另一条仅包含修改的字段值。正因为Delta的存在和TClientDataSet在内存中记录数据的特点,所有的改变都没有立即更新加对应的物理存储中,可以根据这些信息在适当的时候恢复,所以TClientDataSet天生具有缓冲更新功能。

为了使数据更新回数据存储源,我们要调用TClientDataSet中对应的方法。如果ClientDataSet与DataSetProvider关联,那么仅需调用TClientDataSet的ApplyUpdates方法即可保存数据的更新,但如果TClientDataSet没有对应的TDataSetProvider存在,而是直接同文件关联,那么,这种方式是非常有趣的,我们在BriefCase模型中会再次讲解这个问题。

此时,如果使用TClientDataSet的SaveToFile和LoadFromFile,都会保留着Delta。调用MergeChangeLog和ClearChanges后,Delta的内容才会被
清空。

只是前者是将Delta的数据同Data结合起来,将改变存储到物理介质上,而ClearChanges则是一股脑儿全部清空,将数据回复到原始状态。

大部分的应用都是将TClientDataSet与TDataSetProvider结合使用的。两者联合使用的行为反映了Borland的设计宗旨,就是要提供一个面向分布式环境的思路。我们下面来慢慢解释。

当我们将TClientDataSet对象的Active属性设为True或者调用其Open方法后,ClientDataSet会向DataSetProvider发送一个取数据包请求。

于是DataSetProvider便会打开对应的数据集,将记录指针指向第一条记录,然后从头到尾依次扫描。对于扫描到的每一条记录,都会将其编码成一个variant数组,我们通常将它称之为数据包。完成扫描后,DataSetProvider会关闭指向的数据集,并将所有的这些数据包传递给ClientDataSet。

在我提供的演示程序中,你可以清楚地看到这种行为(毕竟眼见为实吗!)。程序主界面右边的DBGrid连接到一个

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值