Delphi 确定ClientDataSet有更改的快速方法

Delphi 确定ClientDataSet有更改的快速方法,delphi,delphi-10.1-berlin,tclientdataset,Delphi,Delphi 10.1 Berlin,Tclientdataset,使用Delphi Berlin 我在datamodule(“dmCore”)中有一个嵌套的Clientdataset 对于任何给定的主项,详细表中约有5000条记录(使用2条主记录进行测试) 我在ActionManager中有一个连接到动作的“Post”按钮 它的更新很简单: actPost.Enabled:=dmCore.HasChanges;// checks master for changes function TdmCore.HasChanges: boolean; begin

使用Delphi Berlin

我在datamodule(“dmCore”)中有一个嵌套的Clientdataset

对于任何给定的主项,详细表中约有5000条记录(使用2条主记录进行测试)

我在ActionManager中有一个连接到动作的“Post”按钮

它的更新很简单:

actPost.Enabled:=dmCore.HasChanges;// checks master for changes
function TdmCore.HasChanges: boolean;
begin
  result := False;
  if cdsPSet.Active then
     result:=(cdsPSet.ChangeCount>0);
end;
“HasChanges”很简单:

actPost.Enabled:=dmCore.HasChanges;// checks master for changes
function TdmCore.HasChanges: boolean;
begin
  result := False;
  if cdsPSet.Active then
     result:=(cdsPSet.ChangeCount>0);
end;
不幸的是,在操作的onUpdate中运行CDS.ChangeCount会占用大量CPU时间(>50%)

我没有注意到这种情况发生在非嵌套CD上

是否有一种更简单(更快)的机制可以用来查看CD是否已更改?我不需要计数,只要某处有变化

短暂性脑缺血发作 EdB

尝试该属性。我不能说它会更快,但这是检测数据集中是否有任何更改的方法。因此,在你的情况下,你实际上可以只写:

function TdmCore.HasChanges: boolean;
begin
  Result := cdsPSet.UpdatesPending;
end;

实现您自己的失效机制。这就像一个单一的
布尔
变量一样简单,当它是
True
时,它意味着某些东西已经改变,而当它是
False
时,它意味着什么都没有改变。然后,您将负责为对此数据集所做的每个更改和操作更新此数据集


如果是我,我会创建一个继承类,重写所有内容,并实现一个失效机制。它将比现有的方法轻得多。当然,在设计时使用它并不容易,但它可以在运行时完成任务。

操作的OnUpdate事件不是切换其启用/禁用状态的最佳位置。它一直在发射

您可能希望将其移动到
TDataSource.OnDataChanged
事件。在那里,您可以插入与TAction.OnUpdate中相同的代码,并且只有当您的数据确实发生更改时才会触发该代码。还可以使用TField参数在不同字段之间进行分隔

示例(对不起,我只得到C++ Builder,但在Delphi中看起来是一样的):


不幸的是,UpdateSpend似乎只在东京出现-我仍然在使用Berlin…你是对的,它是在东京添加的(可能是因为你描述的性能原因)。我错过了你的版本信息。很抱歉我能给你的最好建议是尽快离开MIDAS。这比你想象的更糟糕:这个应用程序混合了CD和FDQuery——我使用的是一个需要CD的奇特网格,但是使用FDConnection->FDQuery->DataSetProvider->CDSFireDAC的查询对象可以根据它的属性回答你(如果你直接使用它而没有提供程序)。问题(我相信会发生)是,在这种情况下,缓存发生在MIDAS的客户端数据集中。不清楚我是否有能力有效地做到这一点-我的目标是“愚蠢的标志技巧”-在datamodule中设置布尔“FastHasChanges”标志,并设置/清除任何可以更改数据的地方-然后只检查标志。丑陋,丑陋-但很快就可以做到。谢谢你的投入,如果我突然有更多的空闲时间,我可能会尝试一下!