我在Delphi 2009(Firebird 3.0(中有TIBQuery-TDataSetProvider-TClientDataSet链,我执行MyClientDataSet.ApplyUpdates(0(。在调用 ApplyUpdates(0( 之前,我是否需要调用 CheckBrowseMode 或在此 CDS 上发布。我几乎可以肯定我需要调用Post/CheckBrowseMode,我认为未发布的更新不会应用于IBQuery,我没有支持/反对这种想法的文档,但这样认为是合乎逻辑的。但有时我可以观察到 MyClientDataSet 在 ApplyUpdates(0( 之前处于 [dsInsert, dsEdit] 状态,并且新值仍然发布并保存在查询中。但也有证据和理由反对这一点。所以 - 我很困惑。
当然,我不对TIBQuery使用CachedUpdate(因为有CDS(,这不是关于提交事务的问题,我强烈控制它们,并且排除了该问题。
我做了测试:我把raise Exception
放在MyClientDataSet的BeforePost事件中,MadException给出了跟踪:
TMyDM.MyClientDataSetBeforePost
TDataSet.DoBeforePost
TDataSet.Post
TCustomClientDataSet.Post
TDataSet.CheckBrowseMode
TCustomClientDataSet.ApplyUpdates
因此,有经验证据表明,CheckBroseMode是自动调用的,但它是偶然的(例如,由于DataSetProvider或ClientDataSet的一些特殊配置(,还是我可以在文档中找到的规则?
还是我可以在文档中找到的规则?
有一个更简单的规则,应该是不言而喻的,我会想:如果CDS的状态是dsEdit或dsInsert,人们可能会认为它处于更改挂起状态 - 已经进行了更改(例如,在数据库感知控件中(但尚未写回CDS的记录缓冲区(如果它具有嵌套数据,则为缓冲区(。 Otoh,调用 ApplyUpdates 的目的是通过 DSP 将记录缓冲区中的更改写回源数据集。 因此,当CDS在dsEdit/dsInsert中时,不应该尝试调用ApplyUpdates,这似乎是基本的。 在任何情况下,CheckBrowse 模式都由 TCustomClientDataSet.ApplyUpdates 调用:
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: 发布; 结束; 结束;