【问题标题】:Obtain Trigger generated values after ApplyUpdates with a TClientDataSet使用 TClientDataSet 在 ApplyUpdates 之后获取触发器生成的值
【发布时间】:2012-08-21 02:41:23
【问题描述】:

我有一个(火鸟)数据库。对于我的大多数表,我都有一个触发器,它在插入之前触发,它将通过生成器为我创建主键 (PK),并向新插入的记录写入 Created Date 值和 Created By 值。我还有一个更新触发器,它写入更新日期字段和更新者字段。

例如(客户端是我数据库中的一个表):

create trigger t_client_id for client
active before insert
as begin
  new.client_id = gen_id(gen_client_id, 1);
  new.created = current_timestamp;
  new.created_by = current_user;
  new.lock_vn = 1;
end ^

create trigger t_client_update for client
active before update
as begin
  new.updated = current_timestamp;
  new.updated_by = current_user;
end ^   

当我通过我的 ClientDataSet (CDS) 应用更新时 - 通过 TDSProviderConnection 附加到远程 TDataSetProviders,我如何“检索”这些生成的值?如果我编辑一个现有的(这又会调用 t_client_update 触发器,调用 RefreshRecord 将获得 updated 和 updated_by 字段。但是,Doco 说要谨慎使用该方法,因此这可能不是实现此目的的正确方法。我在我调用 ApplyUpdates(-1) 之后直接调用它。

我使用的 CDS 仅包含我尝试编辑的一条记录。对于新记录,CDS 处于 dsInsert 模式。一切都已写入数据库,所以我只需要再次获取这些新数据。我也尝试使用包含表中所有记录的 CDS 来查看它是否更简单但没有任何区别 - 不足为奇。我需要这些信息的原因只是为了在 DB Aware 控件中向用户显示这些值。它们是只读的。

我猜想在使用 PK 编辑现有记录时,我可以在记录上调用 Get,但这对插入没有帮助,因为我不知道新的 PK 是什么。

我尝试将更新应用到我的 CDS 的示例(actDSSave 是一个 TDataSetPost 操作)

  dsState := actDSSave.DataSource.DataSet.State;
  DoApplyUpdates(-1);
  if dsState = dsEdit then
    TClientDataSet(actDSSave.DataSource.DataSet).RefreshRecord;

我正在为附加到远程 DataSetProvider 的数据集使用 TIBQuery。此查询 SQL 是一个简单的 select * from client where client_id = :client_id。我也尝试过将此查询与 TIBUpdateSQL 相关联,并尝试在 DataSetProvider 中将 poAutoRefresh 设置为 true。

那么是否有可能以这种方式获得这些触发器生成的值,还是我需要以不同的方式来处理它?我能想到的另一种方法是创建存储过程,对每个表执行 CRUD 并使用它(使用适当的输入/输出参数来返回这些新数据),但希望我不必走这条路。希望我在这里提供了足够的信息来解释和复制这个问题。

谢谢

编辑 在上面实现,DoApplyUpdates(-1) 是我自己的方法。目前的实现很简单:

FdatCommon.cdsClient.ApplyUpdates(MaxErrorCount);

FdatCommon 是一个包含我的 CDS 的 TDataModule。

【问题讨论】:

  • 对于插入,也许你会做一个单独的查询,既添加新行又返回生成的值?
  • 对于 Firebird 2.1 及更高版本,您可以在 insert 语句中使用 returning 子句。
  • 如果我可以使用 TDatasetProvider 和 TClientDataSet 来利用该功能,我想我可以让它工作 - 我很乐意在编辑/插入之后调用 GET。

标签: delphi delphi-xe2 firebird datasnap tclientdataset


【解决方案1】:

如果在 Post 之后没有新的数据重新查询 (RefreshRecord),您根本无法获得“生成的”值。

这是因为当您调用ApplyUpdates时触发器在服务器端运行,但TClientDataSet默认不刷新发布记录。例如,其他库 FIBPlus 可以选择自动执行此操作。

关于插入,TIBDataSet 有 GeneratorField 属性。使用它,在插入之前分别查询和增加生成器值。因此,即使在插入后,您也会有 PK 值。但请避免在触发器中再次使用它。

MIDAS (TClientDataSet) 是一个很棒的库,但与特定 DBMS 的专用库(例如 FibPlus)相比,他的通用/通用架构松散了 DB 特定功能(例如从插入中检索值)。顺便说一句,我看到了 TpFIBClientDataSet。它与 TpFibDataSet 配合使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 2012-04-22
    • 2023-03-22
    相关资源
    最近更新 更多