Delphi 刷新嵌套在DataSetField中的ClientDataSet

Delphi 刷新嵌套在DataSetField中的ClientDataSet,delphi,ado,master-detail,tclientdataset,Delphi,Ado,Master Detail,Tclientdataset,我几乎已经完成了一些代码来解决去年这个未回答的问题: 人们普遍认为,如果不关闭并重新打开主CD,就不可能从服务器刷新嵌套的详细信息CD,但很明显,这会产生不成比例的网络流量,只刷新单个主行及其详细信息行 我想到了一个简单的方法来刷新细节CD 从服务器和它几乎工作。我下面的代码基本上是临时刷新细节的 将筛选器应用于主ADO查询以将其向下筛选到当前主行,并且在该筛选器生效时, 通过对主CD应用类似的筛选器,然后调用其刷新方法来刷新主CD。这是由主CD余弦事件触发的 只有一个小问题:在我的表单上,以

我几乎已经完成了一些代码来解决去年这个未回答的问题:

人们普遍认为,如果不关闭并重新打开主CD,就不可能从服务器刷新嵌套的详细信息CD,但很明显,这会产生不成比例的网络流量,只刷新单个主行及其详细信息行

我想到了一个简单的方法来刷新细节CD 从服务器和它几乎工作。我下面的代码基本上是临时刷新细节的 将筛选器应用于主ADO查询以将其向下筛选到当前主行,并且在该筛选器生效时, 通过对主CD应用类似的筛选器,然后调用其刷新方法来刷新主CD。这是由主CD余弦事件触发的

只有一个小问题:在我的表单上,以及4个数据集和附带的网格上,我在表单上有一个刷新按钮,它调用我的RefreshcdsMasterAndDetails 也被称为cdsMasterAfterScroll。如果我使用主CD的网格移动主CD,我的代码都可以正常工作,详细CD行与AdoQuery详细信息中的行一起立即正确更新,但是如果我通过单击“刷新”按钮触发它,则CD详细信息行仅在我单击“刷新”按钮时每秒更新一次

我的问题是:为什么当我的代码是从一个按钮点击触发时,而不是从余弦事件触发时,它的效果会有任何不同,因为它可靠地完成了余弦事件调用它应该做的事情,但只有在每隔一次按钮点击触发时才会发生

//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;

尽管进行了大量仔细的观察和调试,我仍然没有一个令人满意的解释来解释为什么我的CD会刷新代码 如果在主CD的余弦事件(其中 详细信息CD始终正确更新,并且在按钮单击处理程序中 “详细信息CD”仅每单击一秒钟更新一次。我想这是什么 与主CD的光标在时间之前已经移动这一事实有关 将调用AfterScroll处理程序,这与我单击按钮的情况不同

但是,我找到了一个简单的解决方法和修复方法

解决方法就是在之前不要调用4个数据集上的DisableControls 正在刷新。然后,细节CD总是正确刷新。任何其他 禁用部分或所有数据集的排列会导致my q的差异。但我不喜欢这种工作方式,因为cdsMaster数据库网格必须在数据中滚动,只需刷新一个主行+其详细信息

解决办法是做一件我经过深思熟虑应该首先做的事情,即强迫 刷新细节ADO查询(使用我的数据,只需调用其刷新,这是我的第一次尝试) 在修复时,引发常见的Ado错误“缺少键列信息” 用于更新…”,尽管服务器上的详细信息表有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问题而进入这个话题时,我会
将代码的更新版本移植到该版本的答案上。

这一点很好。一天多来我一直沉浸在这个问题中,所以我设法把这个问题抛在脑后!我将在mo中编辑它。好吧,我相信在CD中,你可以有多个键字段,但是你对我的问题的解决方案是不完整的。但是,嘿,+1这是一个棘手的解决问题的想法…谢谢。因为多字段键而不完整,你是指什么?由于服务器详细信息表遇到了类似的问题,我的代码与我发布的代码有所不同。因为多字段,但不必担心,因为这很容易更改。不管怎么说,为什么要在卷轴后选择
呢?
?基本上是因为当前主行已更改这一事实是最可靠的事件,因此CDSDeail需要获取一组不同的行。我曾在许多情况下使用过它,由于各种原因,依靠VCL获取正确主记录的详细信息是不切实际的。