如何在ApplyUpdates之前刷新修改的记录到CloneSource?

时间:2014-11-24 19:21:03

标签: delphi delphi-xe tclientdataset

所以我有一个带有嵌套细节的ClientDataset(cdsM1)(cdsD1)。我需要在ApplyUpdates之前打印它,所以我克隆它们(cdsMclone和cdsDclone)并过滤主克隆只是为了只显示一个主记录。

打印后,我需要更新记录。起初我尝试过这样的事情:

cdsMclone.Edit;
cdsMclone.FieldByName('DATEPRINTED').AsString := Now;
cdsMclone.Post;
cdsMclone.ApplyUpdates(0);

但在此之后,如果我在源clientdataset中更改了更多内容,cdsM1.ApplyUpdates(0)会产生冲突(我的意思是你应该在OnReconcileError中回复)。但是这个不应该向用户展示。此外,使用此方法,我向数据库发送至少两个请求。

一种解决方法是使用CloneSource属性。例如:

cdsMclone.CloneSource.Edit;
cdsMclone.CloneSource.FieldByName('DATEWASPRINTED').AsString := Now;
cdsMclone.CloneSource.Post;

这样,我可以毫无顾虑地致电cdsM1.ApplyUpdates(0)。但我真的不喜欢这样。似乎代码正在改变它不应该直接做的事情。此外,如果将来我需要在嵌套细节中更改某些内容,代码将如何显示?

还有其他方法可以将克隆的clientdataset中的更改返回给源吗?

2 个答案:

答案 0 :(得分:1)

我只有D7的Rave 5版本,但以下适用于我,无需在Master表,CloneCursor或其他类似的东西上使用过滤器,只生成当前的Master-Detail报告排在主人。因此,它应该避免你的问题,并避免需要解决方法。

下面显示的MasterConnFirst和MasterConnValidateRow事件处理程序在TRvDataSetConnection上的Delphi IDE中为主服务器设置。

TForm1 = class(TForm)
[...]
  cdsMaster: TClientDataSet;
  cdsDetail: TClientDataSet;
[...]
public
  { Public declarations }
  Recs : Integer;
  BM : TBookmark;
end;

procedure TForm1.btnReportClick(Sender: TObject);
begin
  BM := cdsMaster.GetBookmark;  // place a bookmark on the current Master row
  Recs := 0;  // counter for Master records processed by the report
  RvProject.Execute;
end;

procedure TForm1.MasterConnFirst(Connection: TRvCustomConnection);
begin
  // The following moves the cdsMaster to its current row, causing the RvReport to skip the
  // Master rows preceding it.
  cdsMaster.GotoBookmark(BM);
  cdsMaster.FreeBookmark(BM);
end;

procedure TForm1.MasterConnValidateRow(Connection: TRvCustomConnection; var
    ValidRow: Boolean);
begin
  //  This counts the number of Master records processed and returns ValidRow := False
  //  if the Master current row has already been processed.  This will cause
  //  Master rows after our current one to be skipped by the RvReport.

  Inc(Recs);
  if Recs > 1 then
    ValidRow := False;
end;

无论如何,如果这对你有用,那么这个答案的大部分内容都可能被删除,我将在稍后再做。

说明:

  • TRvDataSetConnection还有一个带有EOF参数的OnEOF事件,根据Rave5开发人员指南,您应该能够在处理完当前主行后设置为True,以生成RVReport认为master没有你感兴趣的行。但是在Rave 5.0.4中,这是D7附带的版本,即使为此事件分配处理程序也会导致报告无法生成。可能是Rave 5.0.4中的一个错误,可能已在更高版本中修复。遗憾的是OnEOF处理程序似乎不起作用,因为使用ValidateRow处理程序看起来效率有点低,考虑到报表引擎仍然需要迭代当前记录引擎之后的主记录。

  • TRvDataSetConnection,DataIndex和DataRows有两个属性假设通过将DataIndex设置为当前记录的RecNo来提供一种更简单的方法来告诉它要处理哪些记录。 DataRows为1. DataIndex工作正常,但DataRows设置似乎被忽略,可能是5.0.4中的另一个错误,但也许它在以后的版本中可以正常工作。

答案 1 :(得分:0)

如果使用CloneCursor()创建克隆,则原始克隆和克隆共享相同的基础数据集。它们不是单独的数据集,只有两个不同的视图进入相同的数据。

您不提供用于将原始数据集限制为1条记录的过滤器的详细信息。但是,我怀疑您对记录的更改与导致您看到的冲突错误的过滤条件相冲突。

使用克隆可以避免这种情况,因为克隆的数据集没有应用此过滤器。它是一个单独的视图,有自己的过滤器。因此没有冲突。

以这种方式通过克隆光标修改基础数据集没有问题。如上所述,克隆和克隆源在同一数据集上运行,因此这似乎可以达到您想要的效果。

您的应用程序的一个方面可以从一些文档中受益,但是,为了那些在未来几个月和几年内维护该代码的代码,使代码中的意图和依赖关系更加明显。