CS结构中成批保存CLIENTDATASET中的数据

2016-02-19 19:55 1 1 收藏

今天给大家分享的是由图老师小编精心为您推荐的CS结构中成批保存CLIENTDATASET中的数据,喜欢的朋友可以分享一下,也算是给小编一份支持,大家都不容易啊!

【 tulaoshi.com - 编程语言 】

 

  这应该不算是什么技巧,估计有数据库方面程序的DELPHI程序员都知道;本来没有写想到
   需要把它写成一篇贴子,但前不久看个别刚入门的兄弟的代码时。才发展他们还在刀
   耕火种,为此才想把它写出来算是对入门的兄弟们的一点帮助,让大侠们见笑了;
    我们都知道TCLIENTDATASET有把对它其中的数据所做的修改记录下来的功能;如果需要还可以将
    修改回复到以前的某个状态,而且结合DATASETPROVIDER还可能自动完成改动到SQL映射,将改动成批提交到数据库中
    这个特性对于写数据库程序来说非常有用。其实我所说的保存CLIENTDATASET的数据也是利用这个特性来实现的;

    代码很简单:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  unit uCDSSave;

  interface

  uses
    SysUtils, Windows, Messages, Classes, Graphics, Controls,
    Forms, Dialogs,Provider,DBClient,DB,Variants;

  type
    TSaveCDS = class (TObject)
    private
      Fileds: TStrings;
      FProvider: TDataSetProvider;
      procedure ReconcileError(DataSet: TCustomClientDataSet; E: EReconcileError;
              UpdateKind: TUpdateKind; var Action: TReconcileAction);
    public
      constructor Create;
      destructor Destroy; override;
      procedure CDSSave(CDS:TClientDataSet;TableName,keyFiled,
              NoSaveFileds:String;KeyUpdate:Boolean=False);
      procedure DataSetProviderUpdateData(Sender: TObject;DataSet:
              TCustomClientDataSet);
      procedure SetCDS(KeyFiled,NoSavefields:string;KeyUpdate:Boolean=False);
      property Provider: TDataSetProvider read FProvider write FProvider;
    end;
   
  implementation
  {
  *********************************** TSaveCDS ***********************************
  }
  constructor TSaveCDS.Create;
  begin
    inherited Create;
    Fileds:=TStringList.Create;
    FProvider:=TDataSetProvider.Create(nil);
    FProvider.UpdateMode:= upWhereKeyOnly ;
    FProvider.Options:=FProvider.Options+[poAllowMultiRecordUpdates];
  end;

  destructor TSaveCDS.Destroy;
  begin
    FreeAndNil(FProvider);
    FreeAndNil(Fileds);
   
    inherited Destroy;
   
  end;

  procedure TSaveCDS.CDSSave(CDS:TClientDataSet;TableName,keyFiled,
          NoSaveFileds:String;KeyUpdate:Boolean=False);
  var
    ErrCount: Integer;
  begin
    CDS.CheckBrowseMode;
    if CDS.ChangeCount1 then Exit;
    CDS.OnReconcileError:= ReconcileError;        //调用保存前客户代码应该先调用SetCDS指定保存的信息;
   // SetCDS(CDS,keyFiled,NoSaveFileds,KeyUpdate);
   // FProvider.ApplyUpdates(CDS.Delta,0,ErrCount)
     try
      CDS.Reconcile(FProvider.ApplyUpdates(CDS.Delta,0,ErrCount));
     finally
      CDS.OnReconcileError:=nil;
     end;

  end;

  procedure TSaveCDS.DataSetProviderUpdateData(Sender: TObject;DataSet:
          TCustomClientDataSet);
  var
    i: Integer;
    v: OLEVariant;
    KeyUpdate: Boolean;
  begin
    varClear(v);
    V:=DataSet.GetOptionalParam('KEYUPDATE');
    if not (VarIsNull(V) or VarIsClear(V)) then KeyUpdate:=true
    else  KeyUpdate:=False;
   
    V:=DataSet.GetOptionalParam('KEYFILED');
    if Assigned(DataSet.FindField(VarToStr(V))) then
      if  KeyUpdate then
       DataSet.FindField(VarToStr(V)).ProviderFlags:=[pfInupdate,pfinKey]
      else
         DataSet.FindField(VarToStr(V)).ProviderFlags:=[pfinKey];
    V:=DataSet.GetOptionalParam('NOSAVEFILEDS');
    if (VarIsNull(V) or VarIsClear(V)) then  Exit;
    Fileds.Clear;
    Fileds.Text:=VarToStr(V);
    if Fileds.Count1 then Exit;                  //将不保存的传过来 ,在这个事件中解析
     //这只是一种方法而已,当然也有其他的方式,如用BYTE数组打包到数据包中;请读者自已考虑实现了;
     for i:=1 to Fileds.Count-1 do
     if Assigned(DataSet.FieldByName(Fileds[i])) then DataSet.FieldByName(Fileds[i]).ProviderFlags:=[];
  end;

  procedure TSaveCDS.ReconcileError(DataSet: TCustomClientDataSet; E:
          EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction);
  begin
    Raise E;  //只是简单的抛出例外,如有自己的处理请自己实现了;
  end;

  procedure TSaveCDS.SetCDS(KeyFiled,NoSavefields:string;KeyUpdate:Boolean=False);
  begin
    CDS.SetOptionalParam('TABLE_NAME' ,TableName,true);//指定要存入的表名;
    CDS.SetOptionalParam('KEYFILED' ,keyFiled,true);//指定要主建名;
    CDS.SetOptionalParam('NOSAVEFILEDS' ,NoSaveFileds,true);//指定不要存入的字段列表;
    if KeyUpDate then
       CDS.SetOptionalParam('KEYUPDATE' ,1,true);//  指定主健是否要更新字段列表

  end;

  

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  end.

  

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  这段代码不一定是最优的实现,主要是想给出一个思路,用时可以根据实际情况改动,例如:本来程序是用的MIDAS来实现,则
    就可以直接用CLIENTDATASET连接中间的TDATASETPROVIDER来实现;有一点要特别说明的是我发现在D5时,在前端的CLIENTDATASET
    中直接设定各个字段的PROVIDERFLAG后不会被打包到Delta传给TDATASETPROVIDER;D7中好象也有此问题,不知是我看错了,还是D的BUG;
    否则就不用那么麻烦自已写代码来处理了;

来源:https://www.tulaoshi.com/n/20160219/1622268.html

延伸阅读
似乎你也注重到了,不管怎么定义,似乎一个链表中的对象都是同一类型的。而实际上,这也是必须的,否则,返回节点中的数据这样的函数的返回值的类型是什么呢?但是,人的要求是无止境的……(省略本人感慨若干百字)。 !-- frame contents -- !-- /frame contents -- 把不同的对象链在一个链表中的目的是为了方便使用,现在一定记住...
怎么保存PPT中的图片?   保存图片的方法:右击需要保存的图片,在随后弹出的快捷菜单中,选另存为图片选项,打开另存为图片对话框,取名保存即可。 小技巧:如果想将整个文稿中的图片都分别保存下来,可以这样操作:打开演示文稿,执行文件→另存为Web页命令,打开另存为对话框(如图八),取名(如片头片尾)保存。系统会将幻...
下面介绍如何操作数据表中的数据。 向数据表中插入数据 1. 向导师信息表中插入数据 (1)在图7.19所示的快捷菜单中选择选项,出现如图7.21所示的界面。可以按照二维表格输入数据。 (2)单击 按钮可以查看输入的数据对应的SQL代码。 (3)数据输入完毕后,单击 按钮可以完成数据的插入。 (4)上述过程对...
标签: 办公软件
 Word虽然是一款文档编辑软件,但它的数据计算功能一点也不弱。下面我们就分别介绍以下四种 Word中的数据计算方法,它们分别是:域计算、“工具计算”按钮、表格计算、外部计算器。 一、用域计算 如果文档中引用的一个数值是通过某个公式计算出来的(如计算一个底面半径为3,高为5的圆锥体的体积),时间长了可能就不知道数值是...
标签: InDesign
线型控制是我们在版面制作中经常遇到的问题。尤其是如何正确的使用缩放功能,是大家必须掌握的。 缩放功能看起来并不难,但实际应用中如果稍不留神就会出现错误。在使用中我们要注意以下几点: 1)尽量使用InDesign工具拦中的缩放工具 一般人都喜欢用手动方式进行缩放,其实这种习惯未必很好,原因是很难对线型进行精确的控...

经验教程

651

收藏

96
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部