gpt4 book ai didi

delphi - 使用 poFetchDetailsOnDemand 刷新嵌套数据集

转载 作者:行者123 更新时间:2023-12-03 14:44:35 25 4
gpt4 key购买 nike

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

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

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

我也尝试过:

DM.ClientDataSet1.Refresh;

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

现在,以下代码似乎可以执行任何操作:

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

最佳答案

谷歌搜索发现许多文章都说,如果不关闭并重新打开主 CDS,就不可能使用嵌套的 ClientDataSet,而在这种情况下,OP 不想这样做。然而...

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

代码如下,包括解释其工作原理和一些潜在问题以及如何避免或解决这些问题的注释。我只用 TAdoQueries 测试了它,为 CDS 的提供者提供数据。

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

我认为我不需要发布 DFM 来配合代码。我只是以通常的主从方式设置 AdoQueries(详细信息查询以主设备的 PK 作为参数),一个指向主 AdoQuery 的 DataSetProvider,一个指向提供者的主 CDS,以及一个指向cdsMaster 的 DataSetField。为了进行实验并了解发生了什么,每个数据集都有 DBGrid 和 DBNavigators。

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

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

我在让我的“解决方案”工作时遇到了一两个问题,这个问题中描述了最棘手的问题: 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;

关于delphi - 使用 poFetchDetailsOnDemand 刷新嵌套数据集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19368070/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com