【问题标题】:How can I detect if ApplyUpdates will Insert or Update data?如何检测 ApplyUpdates 是否会插入或更新数据?
【发布时间】:2010-11-08 23:04:05
【问题描述】:

在 ClientDataSet 的 AfterPost 事件处理程序中,我需要当前记录的 ApplyUpdates 函数是否执行更新或插入的信息。

将为新的和更新的记录执行 AfterPost 事件,我不想声明一个新的 Flag 变量来指示是否正在进行“更新”或“插入”操作。

示例代码:

procedure TdmMain.QryTestAfterPost(DataSet: TDataSet);
begin
  if IsInserting(QryTest) then
     // ShowMessage('Inserting')...
  else
     // ShowMessage('Updating');

  QryTest.ApplyUpdates(-1); 
end;

ApplyUpdate 完成后,应用程序将在 AfterPost 方法中写入日志。所以这个方法是离动作最近的地方,我更喜欢一个完全可以插入到这个事件处理程序中的解决方案。

如何使用 ClientDataSet 实例 QryTest 中的信息实现 IsInserting 函数?

编辑:我会试试 ClientDataSet.UpdateStatus 解释here

【问题讨论】:

  • 你打算做什么?是否进行验证、更新用户界面或一些数据操作?
  • ApplyUpdate 完成后,应用程序将在 AfterPost 方法中写入日志。所以这个方法是最接近动作的地方,我更喜欢一个完全可以插入到这个事件处理程序中的解决方案。在这里检查 Delta 数组似乎是最简单的方法。
  • 如果您在客户端按用户登录,这是最好的地方。如果你想为所有用户集中日志,更好的地方是在 TDataSetProvider 的 AfterApplyUpdates 事件中的服务器端。

标签: delphi dbexpress tclientdataset


【解决方案1】:

将 ClientDataSet.StatusFilter 设置为 TUpdateStatus 值,然后读取 ClientDataSet.RecordCount

例如,

 ClientDataSet1.StatusFilter := [usDeleted];
 ShowMessage(IntToStr(ClientDataSet1.RecordCount));

将返回将要执行的删除查询的数量。

但是,请注意两件事。将 StatusFilter 设置为 usModified 始终包括已修改和未修改的记录,因此您取该值的一半(值 4 表示将执行 2 次更新查询)。此外,将 StatusFilter 设置为 [](一个空集)是您恢复到默认视图(修改、未修改和插入)的方式

确保在执行此操作之前已发布任何未发布的更改,否则可能不会考虑未发布的更改。

【讨论】:

  • 非常感谢,这是最简单的解决方案中缺少的部分!请参阅我在 Fabricio Araujo 的回答中的评论。
【解决方案2】:

ApplyUpdates 不会为您提供该信息 - 因为它可以是插入、更新和删除。

ApplyUpdates 应用存储在 Delta 数组中的更改信息。例如,该更改信息可以包含任意数量的不同类型的更改(插入、删除和更新),所有这些都将应用于同一个调用。

在 TDatasetProvider 上,您有 BeforeUpdateRecord 事件(或类似的事件,睡眠在内存上做了一些有趣的事情 :-))。在将 Delta 的每条记录应用于底层数据库/数据集之前调用该事件,因此是获取此类信息的地方......但 Showmessage 将停止应用过程。

编辑:现在我记得还有另一个选项:您可以将 Delta 分配给另一个 clientdataset Data 属性并读取该记录的数据集 UpdateStatus。 当然,您需要在执行 applyupdates 之前 执行此操作...

var
  cdsAux: TClientDataset;
begin
  .
  . 
  <creation of cdsAux>
  cdsAUx.Data := cdsUpdated.Delta;
  cdsAux.First;
  case cdsAux.UpdateStatus of
    usModified:
      ShowMessage('Modified');
    usInserted:
      ShowMessage('Inserted');
    usDeleted:
      ShowMessage('Deleted'); // For this to work you have to modify  
                              // TClientDataset.StatusFilter  
  end;
  <cleanup code>
end;

【讨论】:

  • 这听起来很不错。如果 ApplyUpdate 仅与一条记录相关,则 Delta 数组将仅包含一个条目,该条目知道它是更新还是插入?所以我只需要一种方法来访问 Delta 中的这些信息。
  • 为什么要使用第二个 CDS?我希望 UpdateStatus 已经在第一个 CDS 中可用,所以我可以直接阅读它。或者 StatusFilter 是为什么需要第二个的答案?
  • 因为有了第二张 cd,您将只拥有 Delta 的内容,仅此而已。但这只是一种替代方法,无需通过数据集提供程序。
  • 这是我梦寐以求的解决方案 - 唯一的补充是数据集需要按照 Cary Jensens 回答中的说明进行过滤,以避免未修改的增量记录。我现在在一个演示中使用它来通过消息代理(Apache ActiveMQ 或 OpenMQ)发送数据库更改通知。
【解决方案3】:

TDataSetProvider 上的BeforeUpdateRecord 事件定义为:

procedure BeforeUpdateRecord(Sender: TObject;  SourceDS: TDataSet; DeltaDS:
                             TCustomClientDataSet; UpdateKind: TUpdateKind;
                             var Applied: Boolean);

参数UpdateKind 表示将如何处理记录:ukModify, ukInsert or ukDelete。你可以这样测试:

procedure TSomeRDM.SomeProviderBeforeUpdateRecord(Sender: TObject;
      SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind;
      var Applied: Boolean);
begin
  case UpdateKind of
    ukInsert :
         // Process Insert;
    ukModify :
         // Process update
    ukDelete :
         // Process Delete
  end;
end;

注意:这个事件签名来自Delphi 7。我不知道它是否在以后的Delphi版本中改变了。

【讨论】:

    猜你喜欢
    • 2017-04-14
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 2017-07-21
    • 2023-03-11
    • 2012-12-06
    • 2015-11-22
    • 1970-01-01
    相关资源
    最近更新 更多