秋·风

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

lazarus/fpc自带的bufDataSet和MemDataSet缺少类似TClientDataSet的Delta功能,这个单元从TDataSet扩展了Delta,可以直接生成增删改的SQL,适用于所有TDataSet。

2024-10-25 高勇高老板增强了GetActionSQL功能:

   function GetActionSQL(const ATableName : String; const AKeyFields: String = ''): String; overload;
   function GetActionSQL(const DataBaseType:string;aTablename: string; AKeyFields: string; aAutoIncFieldname: string = ''; aNotE

2024-08-17
增加blob类型转base64,不过服务器需将base64转为blob保存。
2024-07-04
合并ccc(QQ1650680975)增加的delphi 12.0版(unidac)

2024-06-09:
修正可能
QFDataSetMonitor1.Active:=true放在表打开前设置时数据监控可能会失效的Bug;

2024-06-07:
TDataSetChangesMonitor封装为控件,安装DatasetMonitorPack.lpk就可以

 

 使用方法:

procedure TForm1.FormCreate(Sender: TObject);
begin

  BufDataset2.FieldDefs.Clear;
  BufDataset2.FieldDefs.Add('vstr1', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftString')), 30);
  BufDataset2.FieldDefs.Add('vint1', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftinteger')));
  BufDataset2.FieldDefs.Add('vint2', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftinteger')));
  BufDataset2.CreateDataset;

  memo1.Lines.Clear;
  BufDataset2.Open;

  dcm2:=TQFDataSetMonitor.Create(self);
  dcm2.DataSet:=BufDataset2; //监控BufDataset2的数据变化
  dcm2.ActivateMonitoring;

  {$ifdef linux}
  SQLiteLibraryName:=ExtractFilePath(Application.ExeName)+'libsqlite3.so';
  {$else}
  SQLiteLibraryName:=utf8tocp936(ExtractFilePath(Application.ExeName)+'sqlite3.dll');
  {$endif}
  ZConnection1.Disconnect;
  ZConnection1.Protocol:='sqlite';
  ZConnection1.LibraryLocation:=utf8tocp936(ExtractFilePath(Application.ExeName)+{$ifdef linux}'libsqlite3.so'{$else}'sqlite3.dll'{$endif});
  ZConnection1.Properties.Clear;
  ZConnection1.Properties.Add('encrypted=yes');
  ZConnection1.Properties.Add('cipher=sqlcipher');
  ZConnection1.Properties.Add('sqlcipher=legacy');
  ZConnection1.Properties.Add('legacy=1');
  ZConnection1.Properties.Add('controls_cp=CP_UTF8');
  ZConnection1.Properties.Add('AutoEncodeStrings=True');
  ZConnection1.Database:='demo.db3';
  ZConnection1.Password:='123asd';
  ZConnection1.Connect;
  ZQuery1.Close;
  ZQuery1.SQL.Text:='select * from hardware';
  ZQuery1.Open;
  QFDataSetMonitor1.Active:=true;//激活监控功能

end;

 

2024-06-06:
第1版采用helper class方式,发现受限太多,不适合多DataSet使用,今天改标准的class方法,使用方法也相应有调整。

使用方法:
1、在unit的uses添加DataSetDelta

2、ActivateMonitoring(true)//true--启动Delta功能 false--停止Delta
3、GetActionSQL(const ATableName: String; const AKeyFields: String = '');//根据Delta生成SQL
注意:
使用GetActionSQL后会清空Delta的记录。

BufDataset使用Delta的方法:
dcm1:TDataSetChangesMonitor;
dcm2:TDataSetChangesMonitor;

dcm1:=TDataSetChangesMonitor.Create(self);
dcm2:=TDataSetChangesMonitor.Create(self);
dcm1.DataSet:=BufDataset1; //监控BufDataset1的数据变化
dcm2.DataSet:=BufDataset2; //监控BufDataset2的数据变化
dcm1.ActivateMonitoring(true);
dcm2.ActivateMonitoring;

sql:=dcm1.GetActionSQL('test');//读取Delta生成的SQL
sql:=dcm2.GetActionSQL('demo');

继续开源:
https://github.com/szlbz/DataSetDelta.git

{*******************************************************}
{                                                       }
{ 为lazarus TDataSet增加类似TClientDataSet的Delta功能   }
{                    适用于所有TDataSet                 }
{                                                       }
{                                                       }
{               Copyright(c) 2024-2024                  }
{              秋风(QQ315795176)原创出品                }
{                                                       }
{                 All rights reserved                   }
{                     保留所有权利                      }
{                                                       }
{*******************************************************}

unit DataSetDelta;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, BufDataset, DB, TypInfo, Variants;

type

  TDataStateValue = (dsvOriginal, dsvDeleted, dsvInserted, dsvUpdated);
  TDataStateValues=set of TDataStateValue;

  TDataSetChangesMonitor =class(TComponent)
  private
    FDataState:TDataStateValue;
    Foldvalue:array of Variant;
    FBeforeEdit: TDataSetNotifyEvent;
    FBeforeDelete: TDataSetNotifyEvent;
    FBeforeInsert: TDataSetNotifyEvent;
    FAfterPost: TDataSetNotifyEvent;
    FNewDataSet:TBufDataSet;
    FOldDataSet:TBufDataSet;
    FDataSet:TDataSet;
    procedure CreateMonitorDataSet;
    procedure SetDataSet(AValue: TDataSet);
    procedure BeforeInserts(DataSet: TDataSet);
    procedure BeforeEdits(DataSet: TDataSet);
    procedure BeforeDeletes(DataSet:TDataSet);
    procedure AfterPosts(DataSet: TDataSet);
    function GetChangedCount:int64;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function GetActionSQL(const ATableName : String; const AKeyFields: String = ''): String;
    procedure ActivateMonitoring(AValue:Boolean =true);
    property ChangedCount:int64 read GetChangedCount;
    property DataSet:TDataSet read FDataSet write SetDataSet;
  end;

implementation

 

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, BufDataset, DB, Forms, Controls, Graphics, Dialogs,
  DBGrids, StdCtrls,  Memds,TypInfo,Variants,DataSetDelta,lazutf8;

type

  { TForm1 }

  TForm1 = class(TForm)
    BufDataset1: TBufDataset;
    BufDataset2: TBufDataset;
    Button2: TButton;
    Button3: TButton;
    DataSource1: TDataSource;
    DataSource2: TDataSource;
    DBGrid1: TDBGrid;
    DBGrid2: TDBGrid;
    Memo1: TMemo;
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
  public
    dcm1:TDataSetChangesMonitor;
    dcm2:TDataSetChangesMonitor;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button2Click(Sender: TObject);
var sql:string;
begin
  if BufDataset1.State in [dsEdit, dsInsert] then
    BufDataset1.Post;
  sql:=dcm1.GetActionSQL('test');
  if sql<>'' then
    memo1.Lines.Add(sql);
end;

procedure TForm1.Button3Click(Sender: TObject);
var sql:string;
begin
  if BufDataset2.State in [dsEdit, dsInsert] then
    BufDataset2.Post;
  sql:=dcm2.GetActionSQL('demo');
  if sql<>'' then
    memo1.Lines.Add(sql);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  BufDataset1.FieldDefs.Clear;
  BufDataset1.FieldDefs.Add('test1', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftString')), 30);
  BufDataset1.FieldDefs.Add('test2', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftinteger')));
  BufDataset1.CreateDataset;

  BufDataset2.FieldDefs.Clear;
  BufDataset2.FieldDefs.Add('test11', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftString')), 30);
  BufDataset2.FieldDefs.Add('test12', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftinteger')));
  BufDataset2.FieldDefs.Add('test13', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftinteger')));
  BufDataset2.CreateDataset;

  memo1.Lines.Clear;
  BufDataset2.Open;
  BufDataset1.Open;

  dcm1:=TDataSetChangesMonitor.Create(self);
  dcm2:=TDataSetChangesMonitor.Create(self);
  dcm1.DataSet:=BufDataset1; //监控BufDataset1的数据变化
  dcm2.DataSet:=BufDataset2; //监控BufDataset2的数据变化
  dcm1.ActivateMonitoring(true);
  dcm2.ActivateMonitoring;
end;

end.

 

 

posted on 2024-06-03 11:51  秋·风  阅读(543)  评论(2编辑  收藏  举报