【问题标题】:How to catch SQL generated by Delphi TDataSetProvider?如何捕捉 Delphi TDataSetProvider 生成的 SQL?
【发布时间】:2019-10-25 08:22:07
【问题描述】:

我有 TClientDataSet、TDataSetProvider 和 TIBQuery 链,在执行 CDS.Post 时出现“未准备好的语句”错误,显然,TDataSetProvider 生成的更新语句是错误的。如何捕获此更新 SQL? SQL 监控不适用于我的 IBX 组件。我尝试过使用代码(灵感来自TClientDataset.ApplyUpdates fails with 'SQL not supported' when using SQLDirect components):

procedure TSQLResolver.DoExecSQL(SQL: TWideStringList; Params: TParams);
var
  RowsAffected: Integer;
  TmpList: TStringList;
begin
  TmpList:=TStringList.Create;
  TmpList.LoadFromFile('C:\Test\test.txt');
  RowsAffected := (Provider.DataSet as IProviderSupport).PSExecuteStatement(SQL.Text, Params);
  if not (poAllowMultiRecordUpdates in Provider.Options) and (RowsAffected > 1) then
  begin
    TmpList.Add(SQL.Text);
    TmpList.SaveToFile('C:\Test\test.txt');
    TmpList.Free;
    (Provider.DataSet as IProviderSupport).PSEndTransaction(False);
    Provider.TransactionStarted := False;
    DatabaseError(STooManyRecordsModified);
  end;
  if RowsAffected < 1 then
    DatabaseError(SRecordChanged);
end;

但 Test/test.txt 文件中没有写入任何内容。我在哪里可以放置这样的日志记录代码?

Delphi 2010 但我猜这适用于任何版本的 Delphi。

【问题讨论】:

    标签: delphi interbase tclientdataset tdatasetprovider


    【解决方案1】:

    没有任何内容写入您的日志文件的原因是您添加日志的方式,它只会在更新影响超过一行时执行。 Imo,你的代码应该是

    procedure TSQLResolver.DoExecSQL(SQL: TStringList; Params: TParams);
    var
      RowsAffected: Integer;
      TmpList: TStringList;
    begin
      TmpList:=TStringList.Create;
      try
        TmpList.LoadFromFile('C:\Test\test.txt');
        RowsAffected := (Provider.DataSet as IProviderSupport).PSExecuteStatement(SQL.Text, Params);
        TmpList.Add(SQL.Text);
        TmpList.SaveToFile('C:\Test\test.txt');
        if not (poAllowMultiRecordUpdates in Provider.Options) and (RowsAffected > 1) then
        begin
          (Provider.DataSet as IProviderSupport).PSEndTransaction(False);
          Provider.TransactionStarted := False;
          DatabaseError(STooManyRecordsModified);
        end;
        if RowsAffected < 1 then
          DatabaseError(SRecordChanged);
      finally
        TmpList.Free;
      end;
    end;
    

    无论更新的行数如何,它都应该有效。它还通过在仅有条件地执行的代码中释放 TmpList 来修复您设置的 TmpList 泄漏。顺便说一句,正如所写,您会发现此代码不会记录由Params 中的值输入的值,但很容易将这些值添加到日志中,甚至将它们合并到记录的 SQL.Text 中。

    希望这能解决您当前的问题,但坦率地说,您最好花时间将您的代码简化为mre。我说这有几个原因,首先,我从来没有使用 IBX + DSP/CDS 的“未准备语句”错误,其次,使用 IBX 组件进行日志记录通常可以正常工作,第三,准备 mre 经常会揭示问题的原因。所以我怀疑你没有向我们展示的代码中有错误。

    如果您将 mre 设置为使用 IB 示例数据库之一并将其作为新 q 发布在此处(请不要作为对此的编辑),您更有可能找到准备尝试的读者它自己。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-22
      相关资源
      最近更新 更多