网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Delphi
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.为什么要选择TCAD来开发矢量应用.
.打造Delphi中字符串的replace函数.
.扫雷程序思想讲解.
.一个计算器的代码,欢迎大家点评.
.日历函数单元.
.关于SQLDMO的使用.
.在Delphi中进行指纹仪的二次开发.
.在Delphi中编写控件的基本方法.
.如何用idFTP遍历整个目录----下载.
.扫雷外挂的设计与实现(一).
.一个导出Excel非常快的类.
.Delphi中的字符串.
.Delphi中关于TApplication类的详.
.如何将几个DBGRID里的内容导入同.
.Delphi程序设计之--惯用法.
.怎样知道我的程序是否运行在DELP.
.delphi中的split函数.
.COM与DCOM的区别与联系.
.Dll中导出类--Delphi实战之一.
.如何将C/C++程序转译成Delphi(四).

C\S结构中成批保存CLIENTDATASET中的数据

发表日期:2006-2-4


 

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

  代码很简单:

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.ChangeCount<1 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.Count<1 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;

end.

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

上一篇:解决无法按y轴显示的问题! 人气:4262
下一篇:角点检测算子的代码描述 人气:4190
浏览全部Delphi的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐