【问题标题】:Refresh Nested DataSet with poFetchDetailsOnDemand使用 poFetchDetailsOnDemand 刷新嵌套数据集
【发布时间】:2013-10-22 11:32:45
【问题描述】:

有没有办法只刷新详细数据集而不重新加载所有主数据集?

这是我迄今为止尝试过的:

DM.ClientDataSet2.Refresh;      
DM.ClientDataSet2.RefreshRecord;

我也试过了:

DM.ClientDataSet1.Refresh;

但是上面的方法会刷新整个Master数据集,而不仅仅是当前记录。

现在,下面的代码似乎可以做任何事情:

DM.ClientDataSet1.RefreshRecord;

是否有解决方法或正确的方法来做我想做的事? (也许是插入器...)

附加信息:

ClientDataSet1 = 主数据集

ClientDataSet2 = 详细数据集,如下:*

object ClientDataSet2: TClientDataSet
    Aggregates = <>
    DataSetField = ClientDataSet1ADOQuery2
    FetchOnDemand = False
    .....
end

提供者属性:

object DataSetProvider1: TDataSetProvider
    DataSet = ADOQuery1
    Options = [poFetchDetailsOnDemand]
    UpdateMode = upWhereKeyOnly
    Left = 24
    Top = 104
  end

【问题讨论】:

  • AFAIK,在嵌套的客户端数据集中,您不能将Refresh 用于详细数据集。查看 Cary Jensen 写的 article 并搜索刷新词。
  • 在链接的文章中,作者说没有数据集提供者我无法刷新数据集。好的。那么,刷新整个主数据集的唯一方法是什么?
  • 不是 100% 肯定,但看起来确实如此。无论如何,刷新主数据集有什么问题?
  • 要重新加载的数据太多了。实际的 Master DataSet 有近 1.5 亿条记录,而它的 Detail 只有 150~500 条记录。
  • 我重读了你的问题,发现closed dataset 错误很奇怪。我发现了这个link,它说你应该能够在nested clientDataset 上使用RefreshRecord。我的猜测是配置错误。请查看之前的链接以及this one

标签: delphi dataset delphi-7 tclientdataset


【解决方案1】:

谷歌搜索发现许多文章说,如果不关闭并重新打开主 CDS,则使用嵌套的 ClientDataSets 根本不可能,在这种情况下 OP 不想这样做。不过……

对 q 的简短回答是肯定的,在我测试过的相当简单的情况下,它非常简单,虽然有点啰嗦;正确采取必要的步骤需要一段时间才能弄清楚。

代码如下,包括 cmets 解释它的工作原理和一些潜在问题,以及它如何避免或解决这些问题。我只用 TAdoQueries 为 CDS 的 Provider 进行了测试。

当我开始研究这一切时,很快就发现通常的主人 + 详细信息设置,尽管 Providers + CDS 很乐意从服务器刷新主数据,但他们根本不会刷新 detail 记录,一旦它们从服务器第一次被读取cdsMaster 已打开。当然,这可能是设计使然。

我认为我不需要发布 DFM 来使用代码。我只是以通常的主从方式设置了 AdoQueries(详细查询以主服务器的 PK 作为参数),一个 DataSetProvider 指向主 AdoQuery,一个主 CDS 指向提供程序,一个详细 cDS 指向cdsMaster 的 DataSetField。为了试验并了解发生了什么,每个数据集都有 DBGrids 和 DBNavigators。

简而言之,以下代码的工作方式是将 AdoQuery master 和 CDS masterdown 临时过滤到当前行,然后强制刷新它们的数据和当前 master 行的 dtail 数据。这样做,与我尝试过的任何其他方式不同,会导致嵌套在 cdsMaster 的 DataSet 字段中的详细信息行被刷新。

顺便说一句,我尝试过的其他死胡同包括和不设置 poFetchDetailsOnDemand 为 true,同上 cdsMaster.FetchDetailsOnDemand。显然“FetchDetailsOnDemand”并不意味着 ReFetchDetailsOnDemand!

我遇到了一个或两个问题,让我的“解决方案”正常工作,这个 SO 问题中描述了最棘手的问题: Refreshing a ClientDataSet nested in a DataSetField

我已经验证这可以与 Sql Server 2000(!) 后端一起正常工作,包括从 ISqlW 获取在服务器上触发的行数据更改。我还使用 Sql Server 的 Profiler 验证了刷新中的网络流量仅涉及单个主行及其详细信息。

Delphi 7 + Win7 64 位,顺便说一句。

procedure TForm1.cdsMasterRowRefresh(MasterPK : Integer);
begin
  //  The following operations will cause the cursor on the cdsMaster to scroll
  //  so we need to check and set a flag to avoid re-entrancy
  if DoingRefresh then Exit;
  DoingRefresh := True;

  try
    //  Filter the cdsMaster down to the single row which is to be refreshed.
    cdsMaster.Filter := MasterPKName + ' = ' + IntToStr(MasterPK);
    cdsMaster.Filtered := True;
    cdsMaster.Refresh;
    Inc(cdsMasterRefreshes);  //  just a counter to assist debugging

    //  release the filter
    cdsMaster.Filtered := False;

    // clearing the filter may cause the cdsMaster cursor to move, so ...
    cdsMaster.Locate(MasterPKName, MasterPK, []);
  finally
    DoingRefresh := False;
  end;
end;

procedure TForm1.qMasterRowRefresh(MasterPK : Integer);
begin
  try
    //  First, filter the AdoQuery master down to the cdsMaster current row
    qMaster.Filter := MasterPKName + ' = ' + IntToStr(MasterPK);
    qMaster.Filtered := True;

    //  At this point Ado is happy to refresh only the current master row from the server
    qMaster.Refresh;

    // NOTE:
    //  The reason for the following operations on the qDetail AdoQuery is that I noticed
    //  during testing situations where this dataset would not be up-to-date at this point
    //  in the refreshing operations, so we update it manually.  The reason I do it manually
    //  is that simply calling qDetail's Refresh provoked the Ado "Insufficient key column
    //  information for updating or refreshing" despite its query not involving a join
    //  and the underlying table having a PK

    qDetail.Parameters.ParamByName(MasterPKName).Value := MasterPK;
    qDetail.Close;
    qDetail.Open;

    //  With the master and detail rows now re-read from the server, we can update
    //  the cdsMaster
    cdsMasterRowRefresh(MasterPK);
  finally
    //  Now, we can clear the filter
    qMaster.Filtered := False;
    qMaster.Locate(MasterPKName, MasterPK, []);
    // Obviously, if qMaster were filtered in the first place, we'd need to reinstate that later on
  end;
end;

procedure TForm1.RefreshcdsMasterAndDetails;
var
  MasterPK : Integer;
begin
  if cdsMaster.ChangeCount > 0 then
    raise Exception.Create(Format('cdsMaster has %d change(s) pending.', [cdsMaster.ChangeCount]));
  MasterPK := cdsMaster.FieldByName(MasterPKName).AsInteger;

  cdsDetail.DisableControls;
  cdsMaster.DisableControls;
  qDetail.DisableControls;
  qMaster.DisableControls;

  try
    try
      qMasterRowRefresh(MasterPK);
    except
      //  Add exception handling here according to taste
      //  I haven't encountered any during debugging/testing so:
      raise;
    end;
  finally
    qMaster.EnableControls;
    qDetail.EnableControls;
    cdsMaster.EnableControls;
    cdsDetail.EnableControls;
  end;
end;

procedure TForm1.cdsMasterAfterScroll(DataSet: TDataSet);
begin
  RefreshcdsMasterAndDetails;
end;

procedure TForm1.cdsMasterAfterPost(DataSet: TDataSet);
//  NOTE:  The reason that this, in addition to cdsMasterAfterScroll, calls RefreshcdsMasterAndDetails is
//         because RefreshcdsMasterAndDetails only refreshes the master + detail AdoQueries for the current
//         cdsMaster row.  Therefore in the case where the current cdsMaster row or its detail(s)
//         have been updated, this row needs the refresh treatment before we leave it.
begin
  cdsMaster.ApplyUpdates(-1);
  RefreshcdsMasterAndDetails;
end;

procedure TForm1.btnRefreshClick(Sender: TObject);
begin
  RefreshcdsMasterAndDetails;
end;

procedure TForm1.cdsDetailAfterPost(DataSet: TDataSet);
begin
  cdsMaster.ApplyUpdates(-1);
end;

【讨论】:

  • 很好,我会测试并很快回来提供更多的 cmets。
猜你喜欢
  • 2018-01-26
  • 1970-01-01
  • 1970-01-01
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 2016-06-14
  • 2020-08-24
  • 1970-01-01
相关资源
最近更新 更多