刷新嵌套在DataSetField中的ClientDataSet [英] Refreshing a ClientDataSet nested in a DataSetField

查看:181
本文介绍了刷新嵌套在DataSetField中的ClientDataSet的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've nearly finished some code to solve the problem in this unanswered q from last year:

使用poFetchDetailsOnDemand刷新嵌套数据集

收到的智慧是,无法刷新嵌套详细的CDS从服务器没有关闭并重新打开主CDS,但显然可以产生不成比例的网络流量,只是刷新一个主行及其详细行。

Received wisdom is that it's not possible to refresh the nested detail CDS from the server without closing and re-opening the master CDS, but obviously that can generate a disproportionate amount of network traffic, just to refresh a single master row and its detail rows.

我想到一个直接的方法来刷新服务器的CDS
细节,并且它几乎的工作原理。下面的代码基本上是通过暂时的
来进行详细刷新,它将一个过滤器应用到主ADO查询,以将其过滤到当前主行,而该过滤器有效时,
通过应用程序来刷新主CDS一个类似的过滤器,然后调用它的Refresh方法。这是由主CDS AfterScroll事件触发。

I thought of a straightforward way to refresh the detail CDS from the server and it nearly works. My code below basically does a detail refresh by temporarily applying a filter to the master ADO query to filter it down to the current master row and, while that filter is in effect, refreshing the master CDS by applying a similar filter to it and then calling its Refresh method. This is triggered by the master CDS AfterScroll event.

只有一个少女问题:在我的表单上,以及4个数据集和伴随的网格,我在表单上有一个刷新按钮,它调用我的RefreshcdsMasterAndDetails,这个
也在cdsMasterAfterScroll中调用。如果我使用其网格围绕主CDS移动,我的代码一切正常,并且详细CDS行正确地立即更新,以及AdoQuery详细信息&;但是如果通过单击刷新按钮触发它,CDS细节行只会每隔一秒更新一次,我点击刷新按钮。

There is just one teeny problem: On my form,as well as the 4 datasets and accompanying grids, I have a Refresh button on the form that calls my RefreshcdsMasterAndDetails that's also called in cdsMasterAfterScroll. If I move around the master CDS using its grid, my code all works fine, and the detail CDS rows correctly update immediately, along with those in the AdoQuery detail <>but if I trigger it by clicking the Refresh button, the CDS detail rows only update every second time I click the Refresh button.

我的问题是:为什么当我的代码从按钮点击而不是AfterScroll事件触发时,效果会有什么不同可靠地从AfterScroll事件中做出应该做的事情,但是只有在按钮点击时触发的每隔一段时间?

My question is: Why should there be any difference in the effect of my code when it's triggered from a button click rather than from the AfterScroll event, in as much as it reliably does what it's supposed to do called from the AfterScroll event but only every other time when triggered by a button click?

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


推荐答案

尽管进行了大量的仔细观察和调试,没有一个令人满意的解释,为什么我的CDS刷新代码
行为不同,如果在主CDS的AfterScroll事件中调用,其中
细节CDS总是正确更新,并在一个ButtonClick处理程序中
细节CDS只会每秒点击一次更新。我想象,这是一个
的事情,主要CDS的游标已经移动到
AfterScroll处理程序被调用,不像我点击按钮的情况。

Despite a lot of careful observation and debugging, I still don't have a satisfying explanation of exactly why my CDS refreshing code behaves differently if called in the master CDS's AfterScroll event, where the detail CDS always gets updated correctly, and in a ButtonClick handler where the detail CDS only gets updated every second click. I imagine that it's something to do with the fact that the master CDS's cursor has already moved by the time the AfterScroll handler is called, unlike the situation where I click the button.

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

However, I have found a simple work-around and a fix.

解决方法根本就是不调用DisableControls在
之前的4个数据集进行刷新。然后细节CDS总是被正确刷新。任何其他
置换禁用某些或所有数据集会导致我的q的差异。我不喜欢这个工作,因为cdsMaster DBGrid必须滚动所有的数据,只是ti刷新一个主行+其细节。

The work-around is simply not to call DisableControls on the 4 datasets before doing the refresh. Then the detail CDS always gets refreshed correctly. Any other permutation of disabling some or all the datasets results in the difference my q is about. I don't like this work-around though, because the cdsMaster DBGrid has to scroll all the way through the data, just ti refresh one master row + its details.

修复是做一些反思我应该做的一切,即强制
a刷新详细的ADO查询(我的数据,只是调用其刷新,这是我的第一个尝试
在修复时,尽管在服务器上有详细信息表,但是引发了熟悉的Ado错误Insuffient key column information
for updates ...。

The fix is to do something that on reflection I should have done in the first place, namely to force a refresh of the detail ADO query (with my data, simply calling its Refresh, which was my first attempt at a fix, provokes the familiar Ado error "Insuffient key column information for updating ..." despite the detail table having a PK on the server).

所以,这里是修复:

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;

当我通过研究一个更早的未解答的问题,我将是
将代码的更新版本移植到该代码的答案。

As I got into this by looking into an earlier unanswered SO question, I'll be transplanting an updated version of the code to an answer to that one.

这篇关于刷新嵌套在DataSetField中的ClientDataSet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆