如何在Accuracer中记录特定的表格?

时间:2014-10-29 04:05:03

标签: delphi delphi-7 delphi-xe7 accuracerdb

这样的代码记录所有表插入(来自整个应用程序):

procedure TForm1.ACRDatabase1AfterInsertRecord(Sender: TACRDataSet;
  const TableName: WideString; const FieldValues: TACRArrayOfTACRVariant);
begin
if (AnsiUpperCase(TableName) = AnsiUpperCase(LogTable.TableName)) then
 Exit;
 if (Sender is TACRTable) then
 LogTable.Insert();
 LogTable.FieldByName('EventTime').AsDateTime := Now;
 LogTable.FieldByName('TableName').AsString := TableName;
 LogTable.FieldByName('EventType').AsString := 'Insert ';
 LogTable.FieldByName('Whatever').AsString := FieldValues[4].AsString;
 LogTable.Post();
end;

但是每个表的fieldValues不同,所以你可能会崩溃 应用程序(几乎可以肯定)使用字段值,即它们的索引号。

你怎么克服这个?是否可以单独记录每个表?

1 个答案:

答案 0 :(得分:0)

正如我在评论中提到的,我没有Accuracer,但认为它可能会有所帮助 发布一个执行客户端日志记录的通用方法,它可以捕获值 一个或多个字段,可用于所需数量的数据集。你可能 能够在ACRDatabase1AfterInsertRecord处理程序中使用它的一部分作为其发件人 参数似乎用于标识已插入新行的数据集。

如您所见,有一个LogFields过程可以包含在AfterInsert中 您喜欢的任何数据集的处理程序,这会调用一个单独的GetFieldsToLog过程 添加字段的名称以将给定数据集记录到临时StringList。它' S 只有GetFieldsToLog程序需要适应给定数据集的需要。

procedure TForm1.GetFieldsToLog(ADataSet : TDataSet; FieldList : TStrings);
begin
  FieldList.Clear;
  if ADataSet = AdoQuery1 then begin
    FieldList.Add(ADataSet.Fields[0].FieldName);
  end
  else
    // obviously, deal with other specific tables here
end;

procedure TForm1.LogFields(ADataSet : TDataSet);
var
  TL : TStringList;
  i : Integer;
  ValueToLog : String;
begin
  TL := TStringList.Create;
  try
    GetFieldsToLog(ADataSet, TL);
    for i := 0 to TL.Count - 1 do begin
      ValueToLog := ADataSet.FieldByName(TL[i]).AsString;
      //  do your logging here however you want
    end;
  finally
    TL.Free;
  end;
end;

procedure TForm1.ADOQuery1AfterInsert(DataSet: TDataSet);
begin
  LogFields(DataSet);
end;

顺便说一句,拥有单独的GetFieldsToLog过程的一点是它有助于扩展 客户端日志记录到现有数据集记录中的更改。如果生成此列表 在启动时将其保存在某个地方,您可以在数据集的BeforePost事件中使用它 获取字段的当前值和先前值(使用其Value和OldValue属性), 将它们保存在另一个StringList中并将它们记录在AfterPost事件中。当然, 如果您使用公共商店从多个数据集中获取这些值,则需要进行制作 确保一个数据集的AfterPost在任何其他数据集的BeforePost之前触发,或者执行日志记录 完全在BeforePost内(必须存储旧的和当前的字段值 之前和之后的事情很混乱,在AfterPost中做所有事情会更好, 但不幸的是,AfterPost发生时OldValue已经过时了。

请注意,获取OldValue需要特定的数据集类型才能正确实现 它。但是,并非我所遇到的所有类型的数据集都需要检查。

Btw#2,假设您有这样的程序

procedure TForm1.DoSomething(AnObject : TObject);

那么你可以使用"如果AnObject是......"做这样的事情

var
  AnAdoQuery : TAdoQuery;
begin
  if AnObject is TAdoQuery then begin
    // First, use a cast to assign Sender to the local AnAdoQuery variable
    AnAdoQuery := TAdoQuery(AnObject);
    // Then, we can do whatever we like with it, e.g.
    Caption := AnAdoQuery.Name;
  end;
end;

Otoh,如果由于某种原因(我不能立即想到为什么我们会想,但没关系) 我们只想检查我们已经传递的内容,因为AnObject参数是特定的 对象,我们可以省略演员而只是做

  if AnObject = AdoQuery1 then 
    ShowMessage('Received AdoQuery1');

无论我们传递的实际类别如何,此均等检查都有效 作为AnObject参数,因为所有其他类都是AnObject的后代 声明的类,即TObject。