【问题标题】:Delphi: How to access clientdataset via deltaDelphi:如何通过 delta 访问客户端数据集
【发布时间】:2016-08-08 00:45:38
【问题描述】:

在 TDatasetProvider.OnBeforeUpdateRecord 上,我该怎么做 访问源或原始客户端数据集 发送 DeltaDS 参数?

procedure TdmLoanPayment.dpLoanPaymentBeforeUpdateRecord(Sender: TObject;
    SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind:  TUpdateKind;
    var Applied: Boolean);
var
  sourceCDS: TClientDataset;
begin
  sourceCDS := DeltaDS.???;
  ...
end;

我需要从相应的客户端数据集中访问一些属性。设置是 TSQLDataset/TDatasetProvider/TClientDataset。

编辑: 所有这些麻烦的原因是,我想从 TDatasetProvider 派生一个组件并分配一个默认的 OnBeforeUpdateRecord。

【问题讨论】:

  • 您似乎有些困惑。 SourceDS 是源(原始)数据集,DeltaDS 包含在 SourceDS 中发生的更改。
  • 谢谢肯,但我并不感到困惑。我知道 SourceDS 是什么。我想知道的是哪个 Clientdataset 生成了有问题的 DeltaDS。
  • 当然,在设计时,这不是问题,因为我可以分辨出连接了哪个 CDS。但我正在尝试抽象这个过程。
  • 什么是“默认 OnBeforeUpdateRecord”?是不是提供者的 OnBeforeUpdateRecord 事件?
  • @ValMarinov,我想从 TDatasetProvider 派生/继承一个组件。在这个后代组件上,我将分配一个始终被评估的 OnBeforeUpdateRecord。在此 OnBeforeUpdateRecord 中,我想知道生成/作为传递给此事件的增量的父级的 Clientdataset。

标签: delphi tclientdataset


【解决方案1】:

我认为SourceDS 是我们正在寻找的。​​p>

Sender 参数标识正在应用更新的提供者。

SourceDS 参数是数据来源的数据集。 如果没有源数据集,则此值为 nil (Delphi) 或 NULL (C++)。事件发生时源数据集可能未处于活动状态,因此 在尝试访问其数据之前将其 Active 属性设置为 true。

DeltaDS 参数是包含所有更新的客户端数据集 正在应用。当前记录代表更新 即将申请。

UpdateKind 参数指示此更新是否为 修改现有记录(ukModify),插入新记录 (ukInsert),或要删除的现有记录 (ukDelete)。

Applied 参数控制退出事件后发生的情况 处理程序。如果事件处理程序将 Applied 设置为 true,则提供程序 忽略更新:它既不尝试应用它,也不记录 指示未应用更新的错误。如果事件处理程序 将 Applied 保留为 false,提供程序尝试在之后应用更新 事件处理程序退出。

例如:

procedure TdmLoanPayment.dpLoanPaymentBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind:  TUpdateKind;
var Applied: Boolean);
begin
  ShowMessage(TClientDataSet(SourceDS).Name); // get source name
  ...
end;

编辑

  procedure TdmLoanPayment.dpLoanPaymentBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind:  TUpdateKind;
var Applied: Boolean);
begin
  if SourceDS.Name = 'Name1'then
    ...do something ...
  if SourceDS.Name = 'Name2'then
    ...do something ... 
end;

【讨论】:

  • 谢谢瓦尔。但是您确定可以将 SourceDS 转换为 TClientdataset 吗?因为在我的设置中,SourceDS 将是一个 TSQLDataset。在我的设置(SQLDS => Provider => CDS)中,我正在寻找一种引用 CDS 的方法(这就是源代码)。这在设计时是没有问题的,但我试图在运行时这样做以便封装。
  • 不,我不确定。但是在您的问题和设置中(SQLDS => Provider => CDS)它是 TClientDataSet。
  • 但如果您不确定,可以按原样使用 (TDataSet)。
  • 不,瓦尔,这不是我想要的。我还可以向您推荐我在问题中的编辑以及它下面的 cmets 以进行可能的澄清。
【解决方案2】:

如果您追踪到您的DataSetProvider1BeforeUpdateRecord 的呼叫,您将 看到作为SourceDS参数传递的数据集是Source的数据集 UpdateTree,即 AFAICS,DataSet 属性的数据集 提供者设置为。当然,这 不是 Delta 的 CDS 已经导出(在我的测试用例中它实际上是一个 TAdoQuery)。

查看Provider.Pas中的源代码,我不能立即看到一个 找到 Delta 的源 CDS 身份的方法。我不认为这特别令人惊讶,因为 Provider 的操作是由 CDS 调用的,反之亦然,并且 Provider 需要来自 CDS 的所有数据都是它的 Delta。

另一方面,BeforeUpdateRecord 事件有一个相当公平的赌注 由对您的一个 CDS 上的 ApplyUpdates 的最新、仍待处理的调用触发,因此,如果 您在他们的BeforeApplyUpdates 事件中记下了这一点,这可能会 告诉你你想知道的。我希望这适用于单级更新,但如果 UpdateTree 在嵌套 CDS 上运行,则可能会更加棘手。

如果您的 CDS 都有单独的提供者,但提供者共享一个 BeforeUpdateRecord 事件,您可以使用如下代码识别给定提供者的 CDS:

function TCDSForm.FindCDSForProvider(DataSetProvider: TDataSetProvider):
    TClientDataSet;
var
  i : Integer;
begin
  Result := Nil;
  for i := 0 to ComponentCount - 1 do begin
    if Components[i] is TClientDataSet then
      if TClientDataSet(Components[i]).ProviderName = DataSetProvider.Name then begin
        Result := TClientDataSet(Components[i]);
        Exit;
      end;
  end;
end;

【讨论】:

  • 这可能是获取客户端数据集的唯一方法,尽管这很粗暴。我今晚会试试这个。
猜你喜欢
  • 2014-09-09
  • 2015-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-14
  • 2016-07-17
相关资源
最近更新 更多