Я думал, что выложу это как новый ответ как новый ответ на то, что я теперь понимаю
из комментариев ОП, чтобы быть его конкретной проблемой. ОП хочет сделать, чтобы поймать OldValue
поля набора данных на
сторона сервера , то есть на стороне IBQuery, а не на стороне клиента TDatasetProvider. Я уберу свой предыдущий ответ, как только убедился, что ОП его видел.
Рассмотрим следующий код:
type
TMyIBQuery = Class(TIBQuery)
end;
procedure TForm1.IBQuery1BeforePost(DataSet: TDataSet);
var
OldValue : Variant;
PrvState : TDataSetState;
begin
PrvState := IBQuery1.State;
try
TMyIBQuery(IBQuery1).SetTempState(dsOldValue);
OldValue := IBQuery1.FieldByName('AValue').OldValue;
Memo1.Lines.Add('OldValue: ' + OldValue);
finally
TMyIBQuery(IBQuery1).RestoreState(PrvState);
end;
end;
Если DataSetProvider имеет настройки по умолчанию, IBQuery1BeforePost
- это , а не , вызываемый при
ApplyUpdates
вызывается на CDS, подключенной к DSP, потому что процесс подачи заявки
Обновления обходят обычный процесс редактирования IBQuery.
Однако, если вы установите для свойства ResolveToDataSet
DSP значение True
, IBQuery1BeforePost
Выполняет и правильно извлекает OldValue поля AValue
, которое является WideMemo
поле в моей настройке. Причина, по которой код BeforePost выполняется, конечно, в том, что когда ResolveToDataSet
установлено значение True, используются обычные методы редактирования IBQuery.
Обновление Вот выдержки из проекта, которые я упомянул в комментарии:
Извлечение кода
type
TForm1 = class(TForm)
DataSource1: TDataSource;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
IBDatabase1: TIBDatabase;
IBTransaction1: TIBTransaction;
Memo1: TMemo;
IBEvents1: TIBEvents;
IBQuery1: TIBQuery;
IBUpdateSQL1: TIBUpdateSQL;
LblTrans: TLabel;
Timer1: TTimer;
IBQuery1ID: TIntegerField;
IBQuery1ANAME: TIBStringField;
IBQuery1AVALUE: TWideMemoField;
DBMemo1: TDBMemo;
DataSetProvider1: TDataSetProvider;
CDS1: TClientDataSet;
[...]
end;
[...]
procedure TForm1.FormDestroy(Sender: TObject);
begin
IBQuery1.Close;
if IBTransaction1.InTransaction then
IBTransaction1.Commit;
if IBTransaction1.Active then
IBTransaction1.Active := False;
if IBEvents1.Registered then
IBEvents1.Registered := False;
IBDatabase1.Connected := False;
end;
procedure TForm1.RefreshTable2;
begin
if IBQuery1.Modified then
IBDatabase1.ApplyUpdates([IBQuery1]);
RefreshDS;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
UpdateTransLabel;
end;
procedure TForm1.UpdateTransLabel;
begin
if IBTransaction1.Active then
lblTrans.Caption := 'Trans Active'
else
lblTrans.Caption := 'Trans Inactive';
end;
procedure TForm1.CDS1AfterPost(DataSet: TDataSet);
begin
CDS1.ApplyUpdates(0);
end;
procedure TForm1.DBNavigator1BeforeAction(Sender: TObject; Button:
TNavigateBtn);
begin
if IBQuery1.CanModify then
lblTrans.Caption := lblTrans.Caption + ' RW'
else
lblTrans.Caption := lblTrans.Caption + ' RO'
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := ExtractFileName(Application.ExeName) + ' / ' + IBDatabase1.Params.Values['user_name'];
IBQuery1.Open;
end;
procedure TForm1.IBDatabase1AfterConnect(Sender: TObject);
begin
IBDatabase1.Connected := True;
IBEvents1.Registered := True;
end;
procedure TForm1.IBEvents1EventAlert(Sender: TObject; EventName: string;
EventCount: Integer; var CancelAlerts: Boolean);
begin
Memo1.Lines.Add('Evt: (' + IntToStr(EventCount) + ') ' + EventName);
end;
procedure TForm1.CommitAndRefresh;
begin
IBTransaction1.CommitRetaining;
RefreshTable2;
end;
procedure TForm1.IBQuery1AfterDelete(DataSet: TDataSet);
begin
CommitAndRefresh;
end;
procedure TForm1.IBQuery1AfterPost(DataSet: TDataSet);
begin
CommitAndRefresh;
end;
type
TMyIBQuery = Class(TIBQuery)
end;
procedure TForm1.IBQuery1BeforePost(DataSet: TDataSet);
var
OldValue : Variant;
PrvState : TDataSetState;
begin
PrvState := IBQuery1.State;
try
TMyIBQuery(IBQuery1).SetTempState(dsOldValue);
OldValue := IBQuery1.FieldByName('AValue').OldValue;
Memo1.Lines.Add('OldValue: ' + OldValue);
finally
TMyIBQuery(IBQuery1).RestoreState(PrvState);
end;
end;
procedure TForm1.IBQuery1UpdateError(DataSet: TDataSet; E: EDatabaseError;
UpdateKind: TUpdateKind; var UpdateAction: TIBUpdateAction);
begin
UpdateAction := UpdateErrorForm.HandleError(DataSet, E, UpdateKind);
end;
procedure TForm1.RefreshDS;
var
BM : TBookmark;
begin
BM := IBQuery1.GetBookmark;
try
IBQuery1.Close;
IBQuery1.Open;
finally
if IBQuery1.BookmarkValid(BM) then
IBQuery1.GotoBookmark((BM));
IBQuery1.FreeBookmark(BM);
end;
end;
end.
DFM Extract
object Form1: TForm1
[...]
object LblTrans: TLabel
[...]
Alignment = taRightJustify
Caption = '???'
end
object DBGrid1: TDBGrid
[...]
DataSource = DataSource1
Columns = <
item
Expanded = False
FieldName = 'ID'
Visible = True
end
item
Expanded = False
FieldName = 'ANAME'
Width = 80
Visible = True
end
item
Expanded = False
FieldName = 'AVALUE'
Width = 200
Visible = True
end>
end
object DBNavigator1: TDBNavigator
[...]
DataSource = DataSource1
end
object Memo1: TMemo
[...]
end
object DBMemo1: TDBMemo
[...]
DataField = 'AVALUE'
DataSource = DataSource1
end
object DataSource1: TDataSource
DataSet = CDS1
end
object IBDatabase1: TIBDatabase
Connected = True
DatabaseName = 'LocalHost:D:\Delphi\Interbase\Databases\MA.GDB'
Params.Strings = (
'user_name=SYSDBA'
'password=masterkey')
LoginPrompt = False
DefaultTransaction = IBTransaction1
ServerType = 'IBServer'
TraceFlags = [tfQPrepare, tfQExecute, tfQFetch, tfError, tfStmt, tfConnect, tfTransact, tfBlob, tfService, tfMisc]
AfterConnect = IBDatabase1AfterConnect
end
object IBTransaction1: TIBTransaction
Active = True
DefaultDatabase = IBDatabase1
DefaultAction = TACommitRetaining
Params.Strings = (
'read_committed'
'rec_version'
'nowait')
end
object IBEvents1: TIBEvents
AutoRegister = False
Database = IBDatabase1
Events.Strings = (
'NewRow'
'RowDeleted'
'RowUpdated')
Registered = False
OnEventAlert = IBEvents1EventAlert
end
object IBQuery1: TIBQuery
Database = IBDatabase1
Transaction = IBTransaction1
AfterDelete = IBQuery1AfterDelete
AfterPost = IBQuery1AfterPost
BeforePost = IBQuery1BeforePost
BufferChunks = 1000
CachedUpdates = False
ParamCheck = True
SQL.Strings = (
'select * from table2')
UpdateObject = IBUpdateSQL1
Left = 112
FieldName = 'ID'
Origin = '"TABLE2"."ID"'
ProviderFlags = [pfInUpdate, pfInWhere, pfInKey]
end
object IBQuery1ANAME: TIBStringField
FieldName = 'ANAME'
Origin = '"TABLE2"."ANAME"'
Size = 80
end
object IBQuery1AVALUE: TWideMemoField
FieldName = 'AVALUE'
Origin = '"TABLE2"."AVALUE"'
ProviderFlags = [pfInUpdate]
BlobType = ftWideMemo
Size = 8
end
end
object IBUpdateSQL1: TIBUpdateSQL
RefreshSQL.Strings = (
'Select '
'from table2 '
'where'
' ID = :ID')
ModifySQL.Strings = (
'update table2'
'set'
' ID = :ID,'
' ANAME = :ANAME,'
' AVALUE = :AVALUE'
'where'
' ID = :OLD_ID')
InsertSQL.Strings = (
'insert into table2'
' (ID, ANAME, AVALUE)'
'values'
' (:ID, :ANAME, :AVALUE)')
DeleteSQL.Strings = (
'delete from table2'
'where'
' ID = :OLD_ID')
end
object Timer1: TTimer
OnTimer = Timer1Timer
end
object DataSetProvider1: TDataSetProvider
DataSet = IBQuery1
ResolveToDataSet = True
end
object CDS1: TClientDataSet
Active = True
Aggregates = <>
Params = <>
ProviderName = 'DataSetProvider1'
AfterPost = CDS1AfterPost
end
end
Стол DDL
CREATE TABLE "TABLE2"
(
"ID" INTEGER NOT NULL,
"ANAME" VARCHAR(80),
"AVALUE" BLOB SUB_TYPE TEXT SEGMENT SIZE 80
);
CREATE TRIGGER "GETTABLE2ID" FOR "TABLE2"
ACTIVE BEFORE INSERT POSITION 0
AS
begin
new.ID = gen_id("TABLE2ID", 1);
POST_EVENT('NewRow');
end
CREATE TRIGGER "UPDATETABLE2ROW" FOR "TABLE2"
ACTIVE AFTER UPDATE POSITION 0
AS
begin
POST_EVENT('T2 RowUpdated');
end
COMMIT WORK