【问题标题】:Does TClientDataSet.ApplyUpdates(0) require to execute CheckBrowseMode/Post before?TClientDataSet.ApplyUpdates(0) 之前是否需要执行 CheckBrowseMode/Post?
【发布时间】:2019-11-21 12:36:27
【问题描述】:

我在 Delphi 2009 (Firebird 3.0) 中有 TIBQuery-TDataSetProvider-TClientDataSet 链,我执行 MyClientDataSet.ApplyUpdates(0)。在调用 ApplyUpdates(0) 之前,我是否需要在此 CDS 上调用 CheckBrowseMode 或 Post。我几乎可以肯定我需要调用 Post/CheckBrowseMode,并且我认为未发布的更新不会应用于 IBQuery,我没有支持/反对这种想法的文档,但这样想是合乎逻辑的。但有时我可以观察到 MyClientDataSet 在 ApplyUpdates(0) 之前处于 [dsInsert, dsEdit] 状态,并且新值仍被发布并保存在查询中。但也有证据和理由反对这一点。所以 - 我很困惑。

当然,对于 TIBQuery,我不使用 CachedUpdated(因为有 CDS),这不是关于提交事务的问题,我强烈控制它们并且排除了该问题。

我进行了测试:我将raise Exception 放在 MyClientDataSet 的 BeforePost 事件中,MadException 给出了跟踪:

TMyDM.MyClientDataSetBeforePost
TDataSet.DoBeforePost
TDataSet.Post
TCustomClientDataSet.Post
TDataSet.CheckBrowseMode
TCustomClientDataSet.ApplyUpdates

因此,有经验证据表明 CheckBroseMode 是自动调用的,但这是偶然的(例如,由于 DataSetProvider 或 ClientDataSet 的某些特殊配置)还是我可以在文档中找到的规则?

【问题讨论】:

    标签: delphi tclientdataset tdatasetprovider


    【解决方案1】:

    还是我可以在文档中找到的规则?

    有一个更简单的规则,它应该是不言而喻的,我会想到:如果 CDS 的状态是 dsEdit 或 dsInsert,人们可能会认为它处于待更改状态 - 已经进行了更改(例如DB 感知控件)但尚未写回 CDS 的记录缓冲区(或缓冲区,如果它有嵌套数据)。 Otoh,调用 ApplyUpdates 的目的是通过 DSP 将记录缓冲区中的更改写回源数据集。因此,当 CDS 位于 dsEdit/dsInsert 中时,不应尝试调用 ApplyUpdates,这似乎很简单。在任何情况下,TCustomClientDataSet.ApplyUpdates 都会调用 CheckBrowse 模式

    function TCustomClientDataSet.ApplyUpdates(MaxErrors: Integer): Integer;
    var
      RootDataset: TCustomClientDataset;
    begin
      CheckBrowseMode;
      RootDataset := Self;
      while RootDataset.FParentDataSet <> nil do
        RootDataset := RootDataset.FParentDataset;
      with RootDataset do
        if ChangeCount = 0 then
          Result := 0 else
          Reconcile(DoApplyUpdates(Delta, MaxErrors, Result));
    end;
    

    值得注意的是,如果数据集的状态是 dsEdit 或 dsInsert,CheckBrowseMode 会执行以下三种操作之一:

    • 什么都没有,除了调用 CheckActive 然后 DataEvent(deCheckBrowseMode, 0), 如果数据集的状态不是 dsEdit、dsInsert 或 dsSetKey
    • 如果当前记录已被修改,则调用 Post
    • 否则调用取消。

    过程 TDataSet.CheckBrowseMode; 开始 检查活动; DataEvent(deCheckBrowseMode, 0); 案例状态 dsEdit,dsInsert: 开始 更新记录; 如果修改则发布否则取消; 结尾; dsSetKey: 邮政; 结尾; 结束;

    【讨论】:

    • 正确。事实上,如果您仍处于 dsEdit 或 dsInsert 模式时应用更新,您会收到有关未发布更改的错误。 (我忘记了确切的文字)。
    • @nolaspeaker:抱歉,鉴于 DataSet.CheckBrowseMode 的代码,我看不出这将如何发生 - 请参阅我的答案的补充内容。
    • @nolaspeaker 不用担心,尽管如此我更愿意坐下来纠正;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多