我几乎已经完成了一些代码来解决去年这个未得到答复的q中的问题:
Refresh Nested DataSet with poFetchDetailsOnDemand
接受的智慧是,如果不关闭并重新打开主CDS,就无法从服务器刷新嵌套的详细CDS,但显然这会产生不成比例的网络流量,只需刷新单个主行及其详细行。
我想到了一种刷新细节CDS的简单方法 从服务器和几乎工作。我的代码基本上暂时刷新细节 将过滤器应用于主ADO查询以将其过滤到当前主行,并且当该过滤器生效时, 通过对其应用类似的过滤器然后调用其Refresh方法来刷新主CDS。这是由主CDS AfterScroll事件触发的。
只有一个 teeny 问题:在我的表单上,以及4个数据集和附带的网格,我在表单上有一个刷新按钮,调用我的RefreshcdsMasterAndDetails' s 也在cdsMasterAfterScroll中调用。如果我使用其网格移动主CDS,我的代码一切正常,并且详细CDS行正确更新,以及AdoQuery详细信息中的那些<>但如果我通过单击Refresh按钮触发它,则CDS详细信息行仅在每次单击“刷新”按钮时更新。
我的问题是:为什么我的代码在点击按钮而不是AfterScroll事件时触发的效果会有所不同,因为它可靠地完成它的功能。应该从AfterScroll事件中调用,但只能在按下按钮时触发每隔一次?
//Obviously MasterPKName below is a const and DoingRefresh is a boolean
// flag on the form
procedure TForm1.cdsMasterRowRefresh(MasterPK : Integer);
begin
if DoingRefresh then Exit;
DoingRefresh := True;
try
cdsMaster.Prior;
cdsMaster.Next;
cdsMaster.Filter := MasterPKName + ' = ' + IntToStr(MasterPK);
cdsMaster.Filtered := True;
cdsMaster.Refresh;
cdsMaster.Filtered := False;
cdsMaster.Locate(MasterPKName, MasterPK, []);
finally
DoingRefresh := False;
end;
end;
procedure TForm1.qMasterRowRefresh(MasterPK : Integer);
begin
qMaster.Filter := MasterPKName + ' = ' + IntToStr(MasterPK);
qMaster.Filtered := True;
qMaster.Refresh;
cdsMasterRowRefresh(MasterPK);
qMaster.Filtered := False;
qMaster.Locate(MasterPKName, MasterPK, []);
end;
procedure TForm1.RefreshcdsMasterAndDetails;
var
MasterPK : Integer;
begin
MasterPK := cdsMaster.FieldByName(MasterPKName).AsInteger;
cdsDetail.DisableControls;
cdsMaster.DisableControls;
qDetail.DisableControls;
qMaster.DisableControls;
try
qMasterRowRefresh(MasterPK);
finally
qMaster.EnableControls;
qDetail.EnableControls;
cdsMaster.EnableControls;
cdsDetail.EnableControls;
end;
end;
procedure TForm1.cdsMasterAfterScroll(DataSet: TDataSet);
begin
RefreshcdsMasterAndDetails;
end;
答案 0 :(得分:1)
尽管经过了大量的仔细观察和调试,我仍然无法解释为什么我的CDS刷新代码 如果在主CDS的AfterScroll事件中调用,则表现不同 detail CDS总是正确更新,并在ButtonClick处理程序中 详细信息CDS仅在每次单击时更新。我想这是件好事 与主CDS光标已经移动的事实有关 调用AfterScroll处理程序,与我单击按钮的情况不同。
但是,我找到了一个简单的解决方法和修复方法。
解决方法就是不要在之前调用4个数据集上的DisableControls 做刷新。然后,细节CDS始终正确刷新。任何其他 禁用部分或全部数据集的排列会导致我的q差异。我不喜欢这种解决办法,因为cdsMaster DBGrid必须一直滚动数据,只需刷新一个主行+其详细信息。
解决方法是做一些反思我应该首先做的事情,即强迫 刷新详细的ADO查询(使用我的数据,只需调用它的Refresh,这是我的第一次尝试 在修复时,会引发熟悉的Ado错误" Insuffient键列信息 更新......"尽管详细信息表在服务器上有PK。)
所以,这是修复:
procedure TForm1.qMasterRowRefresh(MasterPK : Integer);
begin
try
qMaster.Filter := MasterPKName + ' = ' + IntToStr(MasterPK);
qMaster.Filtered := True;
qMaster.Refresh;
// Do NOT omit the next 3 lines, needed to ensure that the detail query
// and hence the detail CDS, is refreshed
qDetail.Parameters.ParamByName(MasterPKName).Value := MasterPK;
qDetail.Close;
qDetail.Open;
cdsMasterRowRefresh(MasterPK);
finally
qMaster.Filtered := False;
qMaster.Locate(MasterPKName, MasterPK, []);
end;
end;
当我通过研究一个早期未解答的SO问题进入这个问题时,我会 将代码的更新版本移植到该代码的答案。