TClientDataSet.ApplyUpdates(0) 需要先执行 CheckBrowseMode/Post 吗?
Does TClientDataSet.ApplyUpdates(0) require to execute CheckBrowseMode/Post before?
我在 Delphi 2009 (Firebird 3.0) 中有 TIBQuery-TDataSetProvider-TClientDataSet 链,我执行 MyClientDataSet.ApplyUpdates(0)。在调用 ApplyUpdates(0) 之前,我是否需要在此 CDS 上调用 CheckBrowseMode 或 Post。我几乎可以肯定我需要调用 Post/CheckBrowseMode 并且我认为未发布的更新不会应用于 IBQuery,我没有文档 for/against 这样的想法但是这样想是合乎逻辑的。但有时我可以观察到 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 的某些特殊配置)还是我可以在文档中找到的规则?
or is it rule that I can find in the documentation?
有一个更简单的规则,应该是不言而喻的,我会想:如果CDS的状态是dsEdit或dsInsert,人们可能会认为它处于更改待定状态 - 更改已经完成(例如,在 DB-aware 控件中)但尚未写回 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:
开始
更新记录;
if Modified then Post else Cancel;
结尾;
dsSetKey:
Post;
结尾;
结束;
我在 Delphi 2009 (Firebird 3.0) 中有 TIBQuery-TDataSetProvider-TClientDataSet 链,我执行 MyClientDataSet.ApplyUpdates(0)。在调用 ApplyUpdates(0) 之前,我是否需要在此 CDS 上调用 CheckBrowseMode 或 Post。我几乎可以肯定我需要调用 Post/CheckBrowseMode 并且我认为未发布的更新不会应用于 IBQuery,我没有文档 for/against 这样的想法但是这样想是合乎逻辑的。但有时我可以观察到 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 的某些特殊配置)还是我可以在文档中找到的规则?
or is it rule that I can find in the documentation?
有一个更简单的规则,应该是不言而喻的,我会想:如果CDS的状态是dsEdit或dsInsert,人们可能会认为它处于更改待定状态 - 更改已经完成(例如,在 DB-aware 控件中)但尚未写回 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: 开始 更新记录; if Modified then Post else Cancel; 结尾; dsSetKey: Post; 结尾; 结束;