Recent

Author Topic: Adding Delta functionality similar to TClientDataSet to Lazarus TDataSet  (Read 3883 times)

szlbz

  • New Member
  • *
  • Posts: 39
The bufDataSet and MemDataSet that come with Lazarus lack the Delta functionality similar to TClientDataSet. This unit extends Delta from TDataSet, making it applicable to all TDataSet instances.   
 
How to use: 
1.Add DataSetDelta to the uses clause of your unit. 
2.xxxDataSet.ActivateMonitoring(true); //true--Enable the Delta functionality  false -- Stop Delta function
3.xxxDataSet.GetActionSQL(const ATableName: String; const AKeyFields: String = ''); // Generate SQL based on the Delta 
Note: 
Using GetActionSQL will clear the Delta records. 
 
How to use Delta with BufDataset: 
BufDataset1.ActivateMonitoring(true); // Enable the Delta functionality 
BufDataset1.GetActionSQL('test'); // Generate SQL based on the Delta 
=====================================================================

lazarus/fpc自带的bufDataSet和MemDataSet缺少类似TClientDataSet的Delta功能,这个单元从TDataSet扩展了Delta,可以直接生成相应的SQL,适用于所有TDataSet。
使用方法:
1、在unit的uses添加DataSetDelta
2、xxxDataSet.ActivateMonitoring(true)//启动Delta功能
3、xxxDataSet.GetActionSQL(const ATableName: String; const AKeyFields: String = '')//根据Delta返回相应的SQL

注意:
使用GetActionSQL后会清空Delta的记录

BufDataset使用Delta的方法:
BufDataset1.ActivateMonitoring(true)//启动Delta功能
BufDataset1.GetActionSQL('test');//根据Delta返回相应的SQL

https://github.com/szlbz/DataSetDelta.git
« Last Edit: June 04, 2024, 11:55:21 pm by szlbz »

bpranoto

  • Full Member
  • ***
  • Posts: 183
Re: 为lazarus TDataSet增加类似TClientDataSet的Delta功能
« Reply #1 on: June 04, 2024, 10:14:59 am »
I tried the example, with Lazarus 3.5/fpc 3.2.2 on linux, unfortunately it doesn't compile:

1. Required package rtcsdk_fpc is not found

2. After delete rtcsdk_fpc requirement, compilation failed
Code: Pascal  [Select][+][-]
  1. Compile Project, Target: /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/project1: Exit code 1, Errors: 38, Warnings: 2, Hints: 37
  2. Hint: Start of reading config file /home/bambang/lazarus_3.0.fixes/fpc/bin/x86_64-linux/fpc.cfg
  3. Hint: End of reading config file /home/bambang/lazarus_3.0.fixes/fpc/bin/x86_64-linux/fpc.cfg
  4. Verbose: Free Pascal Compiler version 3.2.2-r0d122c49 [2024/05/21] for x86_64
  5. Verbose: Copyright (c) 1993-2021 by Florian Klaempfl and others
  6. Verbose: Target OS: Linux for x86-64
  7. Verbose: Compiling project1.lpr
  8. Verbose: Compiling unit1.pas
  9. Verbose: Compiling bufdataset.pas
  10. bufdataset.pas(70,14) Note: Virtual method "Seek(LongInt;Word):LongInt;" has a lower visibility (protected) than parent class TStream (public)
  11. bufdataset.pas(71,14) Note: Virtual method "Read(var <Formal type>;LongInt):LongInt;" has a lower visibility (protected) than parent class TStream (public)
  12. bufdataset.pas(72,14) Note: Virtual method "Write(const <Formal type>;LongInt):LongInt;" has a lower visibility (protected) than parent class TStream (public)
  13. bufdataset.pas(789,51) Hint: Parameter "size" not used
  14. bufdataset.pas(793,15) Note: Call to subroutine "function AnsiStrLIComp(S1:PChar;S2:PChar;MaxLen:QWord):LongInt;" marked as inline is not inlined
  15. bufdataset.pas(795,15) Note: Call to subroutine "function AnsiStrLComp(S1:PChar;S2:PChar;MaxLen:QWord):LongInt;" marked as inline is not inlined
  16. bufdataset.pas(797,15) Note: Call to subroutine "function AnsiCompareText(const S1:AnsiString;const S2:AnsiString):LongInt;" marked as inline is not inlined
  17. bufdataset.pas(799,15) Note: Call to subroutine "function AnsiCompareStr(const S1:AnsiString;const S2:AnsiString):LongInt;" marked as inline is not inlined
  18. bufdataset.pas(802,55) Hint: Parameter "size" not used
  19. bufdataset.pas(815,51) Hint: Parameter "size" not used
  20. bufdataset.pas(815,66) Hint: Parameter "options" not used
  21. bufdataset.pas(821,55) Hint: Parameter "size" not used
  22. bufdataset.pas(821,70) Hint: Parameter "options" not used
  23. bufdataset.pas(827,50) Hint: Parameter "size" not used
  24. bufdataset.pas(827,65) Hint: Parameter "options" not used
  25. bufdataset.pas(833,55) Hint: Parameter "size" not used
  26. bufdataset.pas(833,70) Hint: Parameter "options" not used
  27. bufdataset.pas(846,51) Hint: Parameter "size" not used
  28. bufdataset.pas(846,66) Hint: Parameter "options" not used
  29. bufdataset.pas(852,52) Hint: Parameter "size" not used
  30. bufdataset.pas(852,67) Hint: Parameter "options" not used
  31. bufdataset.pas(865,53) Hint: Parameter "size" not used
  32. bufdataset.pas(865,68) Hint: Parameter "options" not used
  33. bufdataset.pas(877,50) Hint: Parameter "size" not used
  34. bufdataset.pas(877,65) Hint: Parameter "options" not used
  35. bufdataset.pas(882,67) Hint: Parameter "options" not used
  36. bufdataset.pas(887,55) Hint: Parameter "size" not used
  37. bufdataset.pas(887,70) Hint: Parameter "options" not used
  38. bufdataset.pas(1659,18) Error: Identifier not found "ftShortInt"
  39. bufdataset.pas(1659,28) Error: Constant Expression expected
  40. bufdataset.pas(1660,18) Error: Identifier not found "ftByte"
  41. bufdataset.pas(1660,24) Error: Constant Expression expected
  42. bufdataset.pas(1660,24) Error: duplicate case label
  43. bufdataset.pas(1665,18) Error: Identifier not found "ftLongWord"
  44. bufdataset.pas(1665,29) Error: Constant Expression expected
  45. bufdataset.pas(1665,29) Error: duplicate case label
  46. bufdataset.pas(1665,34) Error: identifier idents no member "AsLongWord"
  47. bufdataset.pas(1665,49) Error: identifier idents no member "AsLongWord"
  48. bufdataset.pas(1673,18) Error: Identifier not found "ftExtended"
  49. bufdataset.pas(1673,29) Error: Constant Expression expected
  50. bufdataset.pas(1673,29) Error: duplicate case label
  51. bufdataset.pas(1673,34) Error: identifier idents no member "AsExtended"
  52. bufdataset.pas(1673,49) Error: identifier idents no member "AsExtended"
  53. bufdataset.pas(1674,18) Error: Identifier not found "ftSingle"
  54. bufdataset.pas(1674,29) Error: Constant Expression expected
  55. bufdataset.pas(1674,29) Error: duplicate case label
  56. bufdataset.pas(1674,34) Error: identifier idents no member "AsSingle"
  57. bufdataset.pas(1674,47) Error: identifier idents no member "AsSingle"
  58. bufdataset.pas(2189,27) Hint: Variable "ACompareStruct" of a managed type does not seem to be initialized
  59. bufdataset.pas(2539,5) Error: Identifier not found "ftShortint"
  60. bufdataset.pas(2539,15) Error: Constant Expression expected
  61. bufdataset.pas(2539,15) Error: duplicate case label
  62. bufdataset.pas(2540,7) Error: Identifier not found "ftByte"
  63. bufdataset.pas(2540,13) Error: Constant Expression expected
  64. bufdataset.pas(2540,13) Error: duplicate case label
  65. bufdataset.pas(2551,5) Error: Identifier not found "ftLongWord"
  66. bufdataset.pas(2551,18) Error: Constant Expression expected
  67. bufdataset.pas(2551,18) Error: duplicate case label
  68. bufdataset.pas(2568,5) Error: Identifier not found "ftExtended"
  69. bufdataset.pas(2568,18) Error: Constant Expression expected
  70. bufdataset.pas(2568,18) Error: duplicate case label
  71. bufdataset.pas(2569,5) Error: Identifier not found "ftSingle"
  72. bufdataset.pas(2569,18) Error: Constant Expression expected
  73. bufdataset.pas(2569,18) Error: duplicate case label
  74. bufdataset.pas(2946,29) Warning: Symbol "ApplyRecUpdate" is deprecated
  75. bufdataset.pas(3093,36) Error: Identifier not found "SErrUpdatesInProgess"
  76. bufdataset.pas(4402,14) Hint: Local variable "s" of a managed type does not seem to be initialized
  77. bufdataset.pas(4469,29) Hint: Local variable "Buf" does not seem to be initialized
  78. bufdataset.pas(4475,18) Hint: Local variable "Buf" does not seem to be initialized
  79. bufdataset.pas(4478,32) Hint: Variable "AUpdOrder" does not seem to be initialized
  80. bufdataset.pas(4517,13) Warning: Implicit string type conversion from "AnsiString" to "UnicodeString"
  81. bufdataset.pas(4518,48) Error: identifier idents no member "ReadUnicodeString"
  82. bufdataset.pas(4526,24) Hint: Local variable "B" of a managed type does not seem to be initialized
  83. bufdataset.pas(4578,20) Error: identifier idents no member "WriteUnicodeString"
  84. bufdataset.pas(4601,14) Hint: Local variable "s" of a managed type does not seem to be initialized
  85. bufdataset.pas(4799,0) Verbose: There were 38 errors compiling module, stopping
  86. Verbose: Compilation aborted
  87. Verbose: /home/bambang/lazarus_3.0.fixes/fpc/bin/x86_64-linux/ppcx64 returned an error exitcode
  88.  

If it works, it will be very useful. Currently, I use TKbmMemTable for the same feature.

szlbz

  • New Member
  • *
  • Posts: 39
Re: 为lazarus TDataSet增加类似TClientDataSet的Delta功能
« Reply #2 on: June 04, 2024, 11:56:50 am »
Delete  rtcsdk_fpc

Project has been updated, please download again

bpranoto

  • Full Member
  • ***
  • Posts: 183
Code: Pascal  [Select][+][-]
  1. Hint: (11030) Start of reading config file /home/bambang/lazarus_3.0.fixes/fpc/bin/x86_64-linux/fpc.cfg
  2. Hint: (11031) End of reading config file /home/bambang/lazarus_3.0.fixes/fpc/bin/x86_64-linux/fpc.cfg
  3. Free Pascal Compiler version 3.2.2-r0d122c49 [2024/05/21] for x86_64
  4. Copyright (c) 1993-2021 by Florian Klaempfl and others
  5. (1002) Target OS: Linux for x86-64
  6. (3104) Compiling project1.lpr
  7. (3104) Compiling unit1.pas
  8. (3104) Compiling DataSetDelta.pas
  9. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(81,39) Warning: (4046) Constructing a class "TBufDataset" with abstract method "LoadBlobIntoBuffer"
  10. /home/bambang/lazarus_3.0.fixes/fpc/units/x86_64-linux/fcl-db/bufdataset.ppu:bufdataset.pas(620,15) Hint: (5062) Found abstract method: LoadBlobIntoBuffer(<TCustomBufDataset>;TFieldDef;PBufBlobField);
  11. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(95,39) Warning: (4046) Constructing a class "TBufDataset" with abstract method "LoadBlobIntoBuffer"
  12. /home/bambang/lazarus_3.0.fixes/fpc/units/x86_64-linux/fcl-db/bufdataset.ppu:bufdataset.pas(620,15) Hint: (5062) Found abstract method: LoadBlobIntoBuffer(<TCustomBufDataset>;TFieldDef;PBufBlobField);
  13. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(78,27) Note: (5025) Local variable "LFieldValue" not used
  14. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(157,3) Note: (5025) Local variable "s" not used
  15. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(176,3) Note: (5025) Local variable "FieldDef" not used
  16. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(225,34) Error: (5000) Identifier not found "ftOraTimeStamp"
  17. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(294,41) Error: (4025) Incompatible type for arg no. 1: Got "Char", expected "Byte"
  18. /home/bambang/lazarus_3.0.fixes/fpc/units/x86_64-linux/rtl/system.ppu:systemh.inc(1208,10) Hint: (5039) Found declaration: Chr(Byte):Char; InternProc;
  19. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(294,50) Error: (4025) Incompatible type for arg no. 1: Got "Char", expected "Byte"
  20. /home/bambang/lazarus_3.0.fixes/fpc/units/x86_64-linux/rtl/system.ppu:systemh.inc(1208,10) Hint: (5039) Found declaration: Chr(Byte):Char; InternProc;
  21. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(316,53) Error: (4025) Incompatible type for arg no. 1: Got "Char", expected "Byte"
  22. /home/bambang/lazarus_3.0.fixes/fpc/units/x86_64-linux/rtl/system.ppu:systemh.inc(1208,10) Hint: (5039) Found declaration: Chr(Byte):Char; InternProc;
  23. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(316,62) Error: (4025) Incompatible type for arg no. 1: Got "Char", expected "Byte"
  24. /home/bambang/lazarus_3.0.fixes/fpc/units/x86_64-linux/rtl/system.ppu:systemh.inc(1208,10) Hint: (5039) Found declaration: Chr(Byte):Char; InternProc;
  25. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(320,98) Error: (4025) Incompatible type for arg no. 1: Got "Char", expected "Byte"
  26. /home/bambang/lazarus_3.0.fixes/fpc/units/x86_64-linux/rtl/system.ppu:systemh.inc(1208,10) Hint: (5039) Found declaration: Chr(Byte):Char; InternProc;
  27. /home/bambang/Downloads/lazarus/components/tbufdatasetdelta/DataSetDelta/DataSetDelta.pas(320,107) Error: (4025) Incompatible type for arg no. 1: Got "Char", expected "Byte"
  28. /home/bambang/lazarus_3.0.fixes/fpc/units/x86_64-linux/rtl/system.ppu:systemh.inc(1208,10) Hint: (5039) Found declaration: Chr(Byte):Char; InternProc;
  29. DataSetDelta.pas(338) Fatal: (10026) There were 7 errors compiling module, stopping
  30. Fatal: (1018) Compilation aborted
  31. Error: /home/bambang/lazarus_3.0.fixes/fpc/bin/x86_64-linux/ppcx64 returned an error exitcode
  32.  
  33.  

bpranoto

  • Full Member
  • ***
  • Posts: 183
I fixed the errors. Here is the diff file to fix the compilation.

szlbz

  • New Member
  • *
  • Posts: 39
已更新,在linux for aarch64 lazarus 3.4+fpc 3.2.2测试
请重新下载!
 please download again

bpranoto

  • Full Member
  • ***
  • Posts: 183
It will be better if you make your class a descendant of TBuffDataSet instead of a helper class.

With your current approach, the FNewDataSet and FOldDataSet will never be freed, hence memory leaks will be occured.

If you make it as descendant class, you will be able to free them in the destructor.

Thaddy

  • Hero Member
  • *****
  • Posts: 15526
  • Censorship about opinions does not belong here.
It will be better if you make your class a descendant of TBuffDataSet instead of a helper class.

With your current approach, the FNewDataSet and FOldDataSet will never be freed, hence memory leaks will be occured.

If you make it as descendant class, you will be able to free them in the destructor.
There are several places where even the diff is not correct. you should use LineEnding or its alias LineBreak instead of #13#10 for cross platform reasons.
Also, version testing should be either a smaller than or greater than or equal expression and based on fpc_fullversion to avoid tying code to a specific single version:
Code: Pascal  [Select][+][-]
  1. {$if fpc_fullversion >= 30301}
  2. // specific code
  3. writeln('trunk');
  4. {$ifend}
That is I assume you are testing for Freepascal trunk, not Lazarus, because TbufDataset is fpc code, not lazarus code: only the component editor is Lazarus code. It may be that 3_3 resolves to the same, but that is bad coding. (I can't see that from the diff).

That said, it is a good idea.
Personally I would not derive or use a helper class: this code is better to integrate in the current class. Or even better in one of the ancestors as protected virtual abstract and then public override for implementation, but that is a lot more work. OTOH it gives the opportunity to implement delta functionality for all TCustomDataset descendants, which is a better design. The availability of delta functionality is actually not TBufDataset specific.
« Last Edit: June 05, 2024, 06:27:05 am by Thaddy »
My great hero has found the key to the highway. Rest in peace John Mayall.
Playing: "Broken Wings" in your honour. As well as taking out some mouth organs.

szlbz

  • New Member
  • *
  • Posts: 39
It will be better if you make your class a descendant of TBuffDataSet instead of a helper class.

With your current approach, the FNewDataSet and FOldDataSet will never be freed, hence memory leaks will be occured.

If you make it as descendant class, you will be able to free them in the destructor.
xxxDataSet.ActivateMonitoring(false) ---会释放 FNewDataSet and FOldDataSet

bpranoto

  • Full Member
  • ***
  • Posts: 183
Thank you Thaddy,

Also, version testing should be either a smaller than or greater than or equal expression and based on fpc_fullversion to avoid tying code to a specific single version:
Code: Pascal  [Select][+][-]
  1. {$if fpc_fullversion >= 30301}
  2. // specific code
  3. writeln('trunk');
  4. {$ifend}
That is I assume you are testing for Freepascal trunk, not Lazarus, because TbufDataset is fpc code, not lazarus code: only the component editor is Lazarus code. It may be that 3_3 resolves to the same, but that is bad coding. (I can't see that from the diff).

Thank you.

Quote
That said, it is a good idea.
Personally I would not derive or use a helper class: this code is better to integrate in the current class. Or even better in one of the ancestors as protected virtual abstract and then public override for implementation, but that is a lot more work. OTOH it gives the opportunity to implement delta functionality for all TCustomDataset descendants, which is a better design. The availability of delta functionality is actually not TBufDataset specific.

Yes, I agree.

bpranoto

  • Full Member
  • ***
  • Posts: 183
It will be better if you make your class a descendant of TBuffDataSet instead of a helper class.

With your current approach, the FNewDataSet and FOldDataSet will never be freed, hence memory leaks will be occured.

If you make it as descendant class, you will be able to free them in the destructor.
xxxDataSet.ActivateMonitoring(false) ---会释放 FNewDataSet and FOldDataSet

There is a big possibility we forget to do this. Even in your example you don't do this.

 Try to compile with use heaptrc unit (-gh) you'll see the memory leaks.

szlbz

  • New Member
  • *
  • Posts: 39
谢谢您的建议,已添加释放FNewDataSet和FOldDataSet
请重新下载!

Code: Pascal  [Select][+][-]
  1. finalization
  2.   FBeforeEdit:=nil;
  3.   FBeforeDelete:=nil;
  4.   FBeforeInsert:=nil;
  5.   FAfterPost:=nil;
  6.   Foldvalue:=nil;
  7.   if FNewDataSet<>nil then
  8.     freeandnil(FNewDataSet);
  9.   if FOldDataSet<>nil then
  10.     freeandnil(FOldDataSet);
  11.  

bpranoto

  • Full Member
  • ***
  • Posts: 183
FNewDataSet and FOldDataSet are regular variables, this mean no more than 1 instance of TBufDataSet can use this helper at the same time, right?

szlbz

  • New Member
  • *
  • Posts: 39
helper class受限太多不能用于多个不同的DataSet,所以今天可以修改为:
Code: Pascal  [Select][+][-]
  1. unit DataSetDelta;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, BufDataset, DB, TypInfo, Variants;
  9.  
  10. type
  11.  
  12.   TDataStateValue = (dsvOriginal, dsvDeleted, dsvInserted, dsvUpdated);
  13.   TDataStateValues=set of TDataStateValue;
  14.  
  15.   TDataSetChangesMonitor =class(TComponent)
  16.   private
  17.     FDataState:TDataStateValue;
  18.     Foldvalue:array of Variant;
  19.     FBeforeEdit: TDataSetNotifyEvent;
  20.     FBeforeDelete: TDataSetNotifyEvent;
  21.     FBeforeInsert: TDataSetNotifyEvent;
  22.     FAfterPost: TDataSetNotifyEvent;
  23.     FNewDataSet:TBufDataSet;
  24.     FOldDataSet:TBufDataSet;
  25.     FDataSet:TDataSet;
  26.     procedure CreateMonitorDataSet;
  27.     procedure SetDataSet(AValue: TDataSet);
  28.     procedure BeforeInserts(DataSet: TDataSet);
  29.     procedure BeforeEdits(DataSet: TDataSet);
  30.     procedure BeforeDeletes(DataSet:TDataSet);
  31.     procedure AfterPosts(DataSet: TDataSet);
  32.     function GetChangedCount:int64;
  33.   public
  34.     constructor Create(AOwner: TComponent); override;
  35.     destructor Destroy; override;
  36.     function GetActionSQL(const ATableName : String; const AKeyFields: String = ''): String;
  37.     procedure ActivateMonitoring(AValue:Boolean =true);
  38.     property ChangedCount:int64 read GetChangedCount;
  39.     property DataSet:TDataSet read FDataSet write SetDataSet;
  40.   end;
  41.  
  42. implementation
使用方法改为:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, BufDataset, DB, Forms, Controls, Graphics, Dialogs,
  9.   DBGrids, StdCtrls,  Memds,TypInfo,Variants,DataSetDelta,lazutf8;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     BufDataset1: TBufDataset;
  17.     BufDataset2: TBufDataset;
  18.     Button2: TButton;
  19.     Button3: TButton;
  20.     DataSource1: TDataSource;
  21.     DataSource2: TDataSource;
  22.     DBGrid1: TDBGrid;
  23.     DBGrid2: TDBGrid;
  24.     Memo1: TMemo;
  25.     procedure Button2Click(Sender: TObject);
  26.     procedure Button3Click(Sender: TObject);
  27.     procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
  28.     procedure FormCreate(Sender: TObject);
  29.   private
  30.   public
  31.     dcm1:TDataSetChangesMonitor;
  32.     dcm2:TDataSetChangesMonitor;
  33.   end;
  34.  
  35. var
  36.   Form1: TForm1;
  37.  
  38. implementation
  39.  
  40. {$R *.lfm}
  41.  
  42. { TForm1 }
  43.  
  44. procedure TForm1.Button2Click(Sender: TObject);
  45. var sql:string;
  46. begin
  47.   if BufDataset1.State in [dsEdit, dsInsert] then
  48.     BufDataset1.Post;
  49.   sql:=dcm1.GetActionSQL('test');
  50.   if sql<>'' then
  51.     memo1.Lines.Add(sql);
  52. end;
  53.  
  54. procedure TForm1.Button3Click(Sender: TObject);
  55. var sql:string;
  56. begin
  57.   if BufDataset2.State in [dsEdit, dsInsert] then
  58.     BufDataset2.Post;
  59.   sql:=dcm2.GetActionSQL('demo');
  60.   if sql<>'' then
  61.     memo1.Lines.Add(sql);
  62. end;
  63.  
  64. procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
  65. begin
  66.   if Assigned(dcm1) then freeandnil(dcm1);
  67.   if Assigned(dcm2) then freeandnil(dcm2);
  68. end;
  69.  
  70. procedure TForm1.FormCreate(Sender: TObject);
  71. begin
  72.   BufDataset1.FieldDefs.Clear;
  73.   BufDataset1.FieldDefs.Add('test1', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftString')), 30);
  74.   BufDataset1.FieldDefs.Add('test2', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftinteger')));
  75.   BufDataset1.CreateDataset;
  76.  
  77.   BufDataset2.FieldDefs.Clear;
  78.   BufDataset2.FieldDefs.Add('test11', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftString')), 30);
  79.   BufDataset2.FieldDefs.Add('test12', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftinteger')));
  80.   BufDataset2.FieldDefs.Add('test13', TFieldType(GetEnumValue(TypeInfo(TFieldType), 'ftinteger')));
  81.   BufDataset2.CreateDataset;
  82.  
  83.   memo1.Lines.Clear;
  84.   BufDataset2.Open;
  85.   BufDataset1.Open;
  86.  
  87.   dcm1:=TDataSetChangesMonitor.Create(self);
  88.   dcm2:=TDataSetChangesMonitor.Create(self);
  89.   dcm1.DataSet:=BufDataset1; //监控BufDataset1的数据变化
  90.   dcm2.DataSet:=BufDataset2; //监控BufDataset2的数据变化
  91.   dcm1.ActivateMonitoring(true);
  92.   dcm2.ActivateMonitoring;
  93. end;
  94.  
  95. end.
  96.  
如需要的请重新下载!
« Last Edit: June 06, 2024, 02:15:19 am by szlbz »

bpranoto

  • Full Member
  • ***
  • Posts: 183
看去来更好!

 

TinyPortal © 2005-2018