3

我将两个 ClientDataSet 用于主从关系,并为每个 CDS 使用一个 DataSetProvider。我不对细节使用嵌套 CDS,因为我对主从关系进行了内存过滤。

我遇到的问题是当我需要将更改应用到底层数据库(火鸟)时。对于细节插入,我必须先应用主,对于细节删除,我必须先应用细节(不违反数据库中的主从关系)。到目前为止,一切都很好。但是,当我的详细 CDS 包含 INSERT 和 DELETE 时,我该怎么办?然后我不能在主 CDS 之前或之后应用它。

在不使用嵌套 CDS 的情况下如何处理这种情况?

4

3 回答 3

2

通常,您插入/更新一个主记录,然后处理详细信息(插入、更新、删除)。解决问题的一种方法是将整个操作放在事务中(在进行任何更改之前启动事务),插入/更新主记录(单个记录),执行MasterCDS.ApplyUpdates,使用详细记录,执行DetailCDS.ApplyUpdates并最终提交或回滚整个事务. 由于您的 CDS 处于主/从关系中,因此一旦它们被编辑DetailCDS就会“看到”记录,并且您将在. 这样您就可以保持参照完整性(外键约束),并且可以在.MasterCDSPostApplyUpdatesMasterCDSDetailCDS

此外,两者都有事件,TClientDataSet可以TDataSetProvider让您(几乎)完全控制整个过程,因此请仔细查看所有可用事件。

注意:当我从记忆中解释这一点时,我可能对某些细节有误,但这个想法很重要。尝试一下,您会找到解决方案。

于 2011-11-23T22:50:04.320 回答
0

当使用单独的数据集提供者时,我发现每个 DSP 中的更新都在一个单独的事务中(至少对于 Interbase)。我对此并不关心,但您的应用程序可能要求所有数据集保持一致。

于 2011-11-26T10:12:36.853 回答
0

我会先申请大师,然后再申请细节。

在您删除主记录的情况下,我将通过覆盖BeforeApplyUpdates事件来级联删除详细记录。

当您删除详细信息时,您将再次需要覆盖 BeforeApplyUpdates。如果缺少主记录,请不要费心执行删除。

您可以使用自定义更新命令“跳过”删除详细记录。这样做的唯一原因是阻止 datasnap 本身生成 SQL 命令,然后因为影响的行数 = 0 而失败。我可能会使用类似的东西

IF EXISTS (SELECT * FROM dbo.ParentTable WHERE ParentKey = @ParentKey)
BEGIN
  DECLARE @rowcount INT
  DELETE
    FROM dbo.ChildTable
    WHERE ChildKey = @ChildKey
  SET @rowcount = @@ROWCOUNT
  IF @rowcount <> 1
  BEGIN
    RAISERROR('Record not found.(%d)', 15, 1, @rowcount) WITH SETERROR
  END
END

然后在 BeforeUpdateRecord 事件中调用此命令

case UpdateStatus of
  ukDelete:
    begin
      sqlDeleteChild.Parameters.ParamByName('@ChildKey').Value := DeltaDS.FieldByName('ChildKey').OldValue;
      sqlDeleteChild.Parameters.ParamByName('@ParentKey').Value := DeltaDS.FieldByName('ParentKey').OldValue;
      sqlDeleteChild.Execute;
    end;
  ...
end;
Applied := true;
于 2011-11-24T01:14:58.357 回答