This should not be a skill, it is estimated that the Delphi programmer with a database program is known; if you don't write it, you need to write it into a post, but you will soon look at the code of the brothers who have just started. Only in the development they were still in the knife, I wanted to write it out to the gorgeous brothers, so that the heroes laughed; we all know that tclientDataSet has a modification record on it. The function of the down; if you need to reply to the previous state, and combined with DataSetProvider automatically completes the change to SQL mapping, this feature will be used to write a batch to the database. This feature is very useful for write database programs. In fact, the data I have said to save ClientDataSet is also implemented by this characteristic;
The code is simple:
Unit ucdssave;
Interface
Uses Sysutils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs, Province, 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 ******* Tsavecds ****** ******************************} constructor tsavecds.create; begin inherited create; fileds: = tstringlist.create; fprovider: = TDataSetProvider.create (nil); fProvider.Updatemode: = updHereKeyOnly; fProvider.Options: = fProvider.Options [PoallowMultiRecordupdates]] ;
DESTRUCTOR TSAVDS.DESTROY; Begin FreeAndnil (FreEndnil); Inherited Destroy;
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; // Call before calling the customer code first calls setcds to specify saved information; // 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;
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)) The keyupdate: = true else keyupdate: = false; v: = Dataset.GetoptionalParam ('keyfiled'); if Assigned (Vartostr (V))) The if keyupdate the 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 thr; // will not save, in this event, in this event This is just a way. Of course, there are other ways, if you pack it into the packet with a Byte array; please ask the reader's self-considered; for i: = 1 to fileds.count-1 do if Assigned (DataSet.fieldbyname [i])) The dataset.fieldByname (FileDs [i]). Providerflags: = [];
procedure TSaveCDS.ReconcileError (DataSet: TCustomClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction); begin Raise E; // simply throw an exception if their treatment at your own implements; end; procedure TSaveCDS .SetCDS (KeyFiled, NoSavefields: string; KeyUpdate: Boolean = False); begin CDS.SetOptionalParam ( 'TABLE_NAME', TableName, true); // specify the table to be stored; CDS.SetOptionalParam ( 'KEYFILED', keyFiled, True); // Specify the name of the main building; CDS.SetoptionalParam ('NOSAVEFILEDS', NOSAVEFILEDS, TRUE); // Specify not to be stored in list; if KeyUpdate the cds.setoptionalParam ('Keyupdate', 1, true); / / Specify whether the list is to update the list list
END;
End.
This code is not necessarily an optimal implementation, mainly to give a thinking, can be changed according to the actual situation, for example, the original program is used by MIDAS, you can directly use the CLIENTDATASETProvider to implement; One thing to specifically explain that I found that in D5, I will not be packaged directly to Delta to TDataSetProvider; D7 seems to have this problem after being transmitted to the TDataSetProvider; D7 seems to have this problem. I don't know if I have a mistake. , Or D's bug; otherwise, if you don't have to write code, you have handled it;