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

 

 

转自:http://www.west263.com/info/html/chengxusheji/delphi/20080411/65524.html

 

这应该不算是什么技巧,估计有数据库方面程序的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; 版权申明:本站文章均来自网络,如有侵权,请联系028-86262244-215,我们收到后立即删除,谢谢!

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;
否则就不用那么麻烦自已写代码来处理了;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值