【问题标题】:Faster way to move data from a dataset structure to another (in TDatasetProvider)将数据从数据集结构移动到另一个结构的更快方法(在 TDatasetProvider 中)
【发布时间】:2012-05-01 08:04:25
【问题描述】:

我有一个自定义的 TDatasetProvider,它允许为它提供的任何数据创建新字段。

所以,假设您在原始数据集上获得了以下字段:

  • 客户 ID
  • 姓名
  • 年龄

您需要使用显示位图在 DBGrid 上选择它。好吧,你可以,因为我的 DSP 可以添加 一个名为 Selected 的布尔字段,用于数据集数据。

我现在这样做的方式:

  1. 创建 2 个 TClientDataset 对象(Origin 和 Target)
  2. 在 Origin 中,我加载了从 InternalGetRecords 方法的参数中获取的数据(我覆盖了它)
  3. 在 Target 中,我创建了从 Origin 数据集定义的字段定义,并添加了开发人员在设计时创建的字段定义
  4. 在目标上执行 CreateDataset
  5. 并且,逐行(和逐字段)将数据从源数据库复制到目标数据集
  6. 最后,将 Data 变量作为 InternalGetRecords 的返回值返回。

我真的不知道是否有更优雅(更快)的方法来做到这一点。还有另一种(更快和/或优雅的)方法可以得到这个结果吗?

【问题讨论】:

  • 难道你不能简单地在原始数据集上创建 internalcalc 布尔字段而不会造成混乱吗?
  • 在我制作了这个组件之后,生活变得更轻松了,因为我可以创建 CDS 识别为数据字段的数据字段..
  • 但是你做了很多不必要的工作。创建这些数据字段的意义何在?
  • 他们简化了很多与 TDbGrid 自定义的工作以获得我想要的功能。我还使用它来标记记录是否已导入并根据结果集的主要实体(非规范化)进行排序......并且列表还在继续......
  • 我相信您可以使用 internalcalc 字段实现同样的效果,并且不会以低效的方式复制数据

标签: delphi tclientdataset tdatasetprovider


【解决方案1】:

好像从源数据集加载数据后,可以调用IDSBase.AddField添加更多字段:

uses
  DB, DBCommon, DBClient, DSIntf;

type
  THackClientDataSet = class(TClientDataSet);

procedure EncodeFieldDesc(var FieldDesc: DSFLDDesc;
  const Name: string; DataType: TFieldType; Size, Precision: Integer;
  Calculated: Boolean; Attributes: TFieldAttributes);
begin
  // ... copied from TClientDataSet.EncodeFieldDesc
end;

//...
var
  FldDesc: DSFLDDesc;
begin
  FillChar(FldDesc, SizeOf(FldDesc), 0);
  EncodeFieldDesc(FldDesc, 'SELECTED', ftBoolean, 0, 0, False, []);
  with THackClientDataSet(DataSet) do
    Check(DSBase.AddField(@FldDesc));
  // now you can create a second client dataset and assign it DataSet.Data directly:
  // DataSet2.Data := DataSet.Data;
  // DataSet2 now contains the new field (with empty values in all existing records)
end;

我没有彻底测试它,但上面的简单示例按预期工作,我能够像往常一样导航第二个客户端数据集并编辑所有字段的值。

【讨论】:

  • 似乎是椅子和键盘之间的问题。出色的解决方案。已接受并 +1。
【解决方案2】:

最快的方法是使用CloneCursor。像这样的:

  1. 创建 2 个 TClientDataset 对象(Origin 和 Target)
  2. 在Origin中,加载InternalGetRecords方法参数获取的数据
  3. 在 Target 中,创建从 Origin 数据集定义的字段定义,并添加开发人员在设计时创建的字段定义
  4. Target.CloneCursor(Origin); //there are more params than this, but this is the basic idea
  5. Target 现在将包含与 Origin 相同数据的新视图,但受 Target 上存在的任何字段、过滤器等的限制。 (如果你没有定义任何字段,它会复制 Origin 的字段。如果你定义了字段,那么它会坚持你给它的。)
  6. 从 Target 复制数据,这正是您要查找的内容。

【讨论】:

  • 如果 OP 真的想要额外的 fkData 字段,那将无法工作。如果他只需要一些查找、计算、内部计算或聚合字段,则无需搞乱所有复制/克隆,并且可以使用单个(原始)cd 来实现
  • 我尝试了这个想法,但它不起作用 - 我得到的只是来自 Origin 的数据数组。也许我误解了什么......
【解决方案3】:

我有一个示例,它动态地将字段添加到 CDS,使用匿名方法计算各个字段,以实现更大的灵活性。在打开 CDS 之前,先添加计算字段,然后再打开它..

这就是你要找的吗?问题不是很清楚...

【讨论】:

  • 这应该是评论,而不是答案。
  • 传奇人物 Marco Cantù 回答我的谦虚问题? 酷。 回到工作:我在 cds.open 之后创建数据字段(在 TDataSetProvider 的 InternalGetRecords 上)
【解决方案4】:

您可以使用 TClientDataset 的 Data 属性来复制整个数据集、元数据和数据。这应该是将一个 TClientDataset 复制到另一个的最快方法。

http://docwiki.embarcadero.com/RADStudio/en/Assigning_Data_Directly

【讨论】:

  • -1 似乎您没有阅读问题...目标 CDS 具有不同的元数据(带有附加字段)。因此,如果我真的只是将 Data 变体从 Origin 复制到 Target,我将只拥有它 - 没有所需附加字段的 Origin 副本。
  • 当我阅读您的问题时,您的 Origin 数据集包含您通过自定义 TDatasetProvider 创建的“新”字段,并且字段数据来自您覆盖的 InternalGetRecords。这是我回答的依据。否则,为什么需要自定义 TDatasetProvider?您可以在从 Origin 复制字段信息的同时在 Target 中创建新字段。
  • 你读错了。目标具有新字段。 Origin 获取从数据集提供者的参数中获取的数据(“纯”数据获取数据访问组件)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-07
  • 1970-01-01
  • 2021-11-04
相关资源
最近更新 更多