创建与 TDataSet 关联的 Persistent Field 组件的代码

Posted

技术标签:

【中文标题】创建与 TDataSet 关联的 Persistent Field 组件的代码【英文标题】:Code to create Persistent Field components associated with TDataSet 【发布时间】:2011-09-25 11:47:31 【问题描述】:

寻找一些示例代码来说明如何在运行时创建与数据集关联的 TField 组件。

在 IDE 中,如果您按下数据集组件,右键单击会调出在设计时提供此功能的字段编辑器。无法找到显示如何在运行时执行此操作的代码。

TIA

【问题讨论】:

你想完成什么?如果要避免在循环中使用 FieldByName,您可以将 TField 变量添加到方法中,使用 FieldByName 分配一次,然后在循环中使用 vars... 您可能在运行时需要 FIELDS,而不是 PERSISTENT FIELDS。 @Marjan 例如,这允许在运行时动态创建计算/查找字段,或者创建一个未绑定到真实数据库(连接)但简单的内存数据的数据集 @mjn - +1 - 见下面我的 cmets - 这正是我需要做的。 【参考方案1】:

在运行时创建的“持久字段”没有意义。在 IDE 中创建持久字段允许将它们写入表单/数据模块的 .dfm,然后在从可执行文件加载该 .dfm 时自动创建,并且可以在使用该数据模块的代码中按名称访问。

如果你不想在运行时使用FieldByName,你可以这样做:

TMyDataModule=class(TDataModule)
  // Usual IDE created stuff, etc.
public
  NameFld: TStringField;
  LimitFld: TFloatField;
end;

procedure TMyDataModule.DataModuleCreate(Sender: TObject);    
begin
  NameFld := MyDataSet.FieldByName('CompanyName') as TStringField;
  NameFld.Required := True;
  LimitFld := MyDataSet.FieldByName('CreditLimit') as TFloatField;
  LimitFld.Currency := True;
  // Set other properties as needed.
end;

您现在在运行时拥有等效的持久字段。可以在使用您的数据模块的其他代码中照常访问它们。

procedure TMyDataModule.DoSomethingWithData(CompanyName: string; CreditLimit: Currency);
begin
  MyDataSet.Edit;
  NameFld.AsString := CompanyName;
  LimitFld.AsCurrency := CreditLimit;
  MyDataSet.Post;
end;

编辑:只是想到了我的陈述“毫无意义”的两个例外 - 那些将被计算或查找字段。对于查找字段,最简单的方法是通过 JOIN 将它们添加到 SQL 并让服务器完成;对于计算字段,您可以使用DataSet.FieldDefs.Add 并设置适当的属性来命名字段,将新创建的字段的FieldType 设置为ftCalculated,并分配一个OnCalcFields 事件处理程序来处理计算。

【讨论】:

我回滚了您的编辑,因为它改变了整个问题(因此也改变了答案)。将来,问你真正想回答的问题——如果你不能清楚地陈述这个问题,就很难提供准确的回答。 “持久”是您要求的,而“持久”是我回答的。如果这不是您想要的,请将其删除并提出一个新问题,而不是事后完全改变主题(或含义)。 另外,它没有意义,因为如果你可以在运行时创建它,然后将它写入文件,你可以在运行时创建它而忘记文件;下一次运行可以在运行时再次创建它们。 ReadComponent/WriteComponent 在您的问题上下文中没有意义;这不是问的问题。 @Ken-至于我需要做什么,我有一个非常古老的应用程序,其中充满了具有许多持久字段的 TTable 组件,其中许多是计算字段,在设计时创建 + 数千行通过组件名称引用 TfieldComponents 而不引用数据集的代码。现在,我必须复制该功能并移动一些代码,但要在内存数据集中使用。不想在数据模块上放下数百个组件并将所有内容隐藏起来——我只想要透明代码。因此,我的问题。如前所述,不是寻求解决方法,而是如何完成一项特定任务。 @Mikey - 也有应有的尊重,但你的说法是不合理的。正确答案是来自 Delphi 帮助的 sn-p。我认为这是微不足道的。如果你和你的伙伴是老德尔福家伙,那应该是毫无疑问的。正如 Ken 反复说的:从技术上讲,通过代码生成许多字段是没有意义的。我认为你的方法是错误的。如果你必须复制这个,我现在会用设计时生成的字段来做。 @Andreas:你说得很好——但我查看了 Delphi 帮助,但不确定要查找什么——所有内容都与设计师有关。帮助中可能有一些东西,但如果它是你从不做的事情,它并不总是很容易找到 - 我是一个按小时付费完成任务的承包商,而且通常比不完整的 Delphi 帮助更快地获得我的信息我们现在有。就像调试代码一样——“另一双眼睛”。在设计时?我讨厌不得不挖掘嵌入式组件(或 DFM)来找出代码在做什么,并且不希望其他人这样做。【参考方案2】:

每个字段类型都有一个创建函数,您将 DataSet 传递给该函数会创建该类型的字段并将其添加到字段中。来自 DB.TStringField.Create 的帮助。

var
  T: TStringField;
begin
  SQLDataSet1.Close;
  T := TStringField.Create(SQLDataSet1);
  T.FieldName := 'LastName';
  T.Name := SQLDataSet1.Name + T.FieldName;
  T.Index := SQLDataSet1.FieldCount;
  T.DataSet := SQLDataSet1;
  SQLDataSet1.FieldDefs.UpDate;
  SQLDataSet1.Open;
end;

【讨论】:

这真的什么也没做。使用零代码打开数据集将为您做同样的事情,除非数据集仅在内存中并且尚未持久化到磁盘(例如,TClientDataSet,您无法使用 LoadFromFile 或从现有的数据库提供者)。唯一的区别是您将拥有一个名为“DataSetNameFieldName”的字段,您现在可以通过FieldByName 访问该字段。请注意,我没有否决您的回答;只是提到这大部分都是零功能代码。 实际上这似乎是正确的答案:这段代码创建了一个绑定到数据集的 tcomponent 后代。请不要担心我想要完成什么或我将获得什么 - 如果可以的话,最好只是阅读问题并回答它。放心,我知道我想完成什么。 @Mikey:太好了。关键是 我们 需要知道您想要完成什么才能回答您的问题 - “只需阅读问题并回答它”是不可能的,并且对试图帮助的人无礼会赢得不会让你走远(就像未来的建议一样)。我本可以简单地将您的问题否决为不清楚,或者投票将其关闭为“不是一个真正的问题”。如果您的意图不明确,则更难回答问题。

以上是关于创建与 TDataSet 关联的 Persistent Field 组件的代码的主要内容,如果未能解决你的问题,请参考以下文章

Delphi中JSon SuperObject 使用:数据集与JSON对象互转

使用学生数据集进行关联规则挖掘

delphi 如何通过Tdataset数据集 获取数据库列名以及列数?

Delphi定位TDataSet数据集最后一条记录

UNIGUI下载文件

创建网络节点,并与报文信号进行关联