Delphi:如何使用TClientDataset作为内存数据集

26
根据此页面,可以将TClientDataset作为内存数据集使用,完全独立于任何实际的数据库或文件。它描述了如何设置数据集的表结构以及如何在运行时加载数据。但是,在D2009中按照其说明进行操作时,第4步(table.Open)引发了异常。它说没有指定提供程序。
那个页面的整个示例的重点是构建一个不需要提供程序的数据集。这个页面是错的、过时的还是我漏掉了哪一步呢?如果那个页面错了,我应该使用什么代替来创建一个完全独立的内存数据集呢?我一直在使用TJvMemoryData,但如果可能的话,我想减少我的项目添加到其中的额外依赖项。
11个回答

25

在运行时,您可以使用table.CreateDataset,如果这是在设计表面上,您可以右键单击CDS并单击创建数据集。但在此之前,您需要指定CDS的列/类型。


点击“创建数据集”?在XE2中,右键单击TClientDataset时没有这样的选项。 - Warren P
1
它存在于XE7中,从顶部开始数第五个选项。 - BIBD

23

如果需要更进一步的帮助,这里有一段代码。我创建了一个ClientDataset作为内存表:

procedure TfrmPRMain.ConfigureDataset;
begin
  With cdsMain do begin
    FieldDefs.Add('bDelete', ftBoolean);
    FieldDefs.Add('sSource', ftString, 10);
    FieldDefs.Add('iSection', ftInteger);
    FieldDefs.Add('iOrder', ftInteger);
    FieldDefs.Add('sBranch', ftString, 10);
    FieldDefs.Add('sPulseCode', ftString, 10);
    FieldDefs.Add('sCode', ftString, 10);
    FieldDefs.Add('dtWorkDate', ftDate);
    FieldDefs.Add('iWorkWeek', ftInteger);
    FieldDefs.Add('sName', ftString, 50);
    CreateDataSet;
    LogChanges := False;
    Open;
  end;
end;

您只需替换自己的数据信息并进行操作。 Jack


4
不需要调用Open函数。 - Erick Sasse
“CreateDataSet” 命令在我的 Delphi 10.1 Berlin Starter 中导致了 NullPointer 访问冲突。 - Daniel Marschall
1
@DanielMarschall 这段代码假定 cdsMain 已经引用了一个现有的 TClientDataSet 实例,该实例可以在设计时添加到表单中,也可以在运行时从代码中创建。 - GolezTrol

9

别忘了在你的安装程序中包含MIDAS.DLL文件,或者在uses语句中简单地包含MidasLib。否则,在客户机上使用TClientDataSet时会引发错误。这可能很明显,但我曾经忘记过这一点。


2
如果您想包含MidasLib,请注意此错误 - Alois Heimer

7
您可以使用 table.CreateDataSet

6
这个页面上的代码在任何 Delphi 版本中都无法工作。调用 CreateDataSet 已经将数据集置于活动状态(“已打开”)。您应该只使用 .CreateDataSet 或 .Open,而不是两者都使用。
当您想要从提供程序(通过 ProviderName 属性)获取数据时,请使用 .Open。当您想要自己填充数据集时,请使用 .CreateDataSet。
顺便说一下:有关 ClientDataSets 及其功能的深入参考,请查看 CodeGear Developer Network 上优秀的 Cary Jensen 文章(首先阅读最早的文章)。

3
如果您需要一个无依赖、高质量、功能丰富(更不用说免费了!)的内存数据集,我强烈推荐 kbmMemTable。它可以完成 TClientDataset 的所有功能,甚至更多。

是的,它确实有那个方法。 - Tim Sullivan
功能集非常强大。不幸的是,它在D2009下无法编译。 - Mason Wheeler
根据他们的新闻,它支持D2009:http://www.components4programmers.com/news/kbmmemtablev_6_00professionalsta.htm - Tim Sullivan
是的,在6版本下。但实际的下载页面似乎没有6版本的链接,这对公司形象不太好... - Mason Wheeler
1
我确信这只是一个疏忽,发送一封快速的电子邮件就可以解决问题。 C4D在Delphi社区已经活跃了十多年,所以他们绝不是一个昙花一现的组织。 - Tim Sullivan

1

以下是一些自由组件的墓地石碑

在 Delphi 5 / Delphi 7 时代,有一些倡议将具有发布属性(更准确地说是数组或某些集合)的任何对象转换为数据库。在 Torry.net 上,这些是 CollectionDataSet 和 Object DataSet。比 LINQ 等早了很多年。

但由于 DB-VCL 代码很少有文档,并且自 Delphi 1.0 的 16 位版本以来就已经成为意大利面条代码 - 这些组件已经没有开发了。

还有基于回调(事件)的 Snap Object Dataset,不太过时。虽然我认为它让开发人员承担了太多责任。

TDBF.sf.net 表格曾经有内存模式,但很快就被删除了。TDBF 也已经死亡。

rxLib/JediVCL 有 MemoryDataset。虽然 rxLib 的目标是从 16 位 Delphi 1 到 Delphi 5 的源级兼容性。但这使得代码变得非常脆弱。在 JVCL 中,它受到了一些关注和老化代码的清除,但在需要进行比平凡使用更深入的操作时仍然是半成品。

还有一些免费供个人使用的 DCU 组件,例如 SQLMemoryTable,但不适用于最近的版本。我想知道 Firebird Embedded / SQLite 是否可以用于创建内存表,而无需使用像 RAMdrive 这样的系统范围黑客技巧 :-)


没有研究所需的SQLite版本,但SQLite是一个非常出色的内存数据库。只需使用文件名“:memory:”打开数据库参见参考页面以获取更多详细信息和用途。内存数据集的开销很大,但功能非常强大,并且可以轻松切换到基于磁盘的版本,这对于实际存储数据进行调试非常有用。 - Gary Walker
@GaryWalker AnyDAC(今天 - FireDAC)确切地为其内存表提供了sqlite后端。不确定这是否是个好主意。他们倾向于跨越自己的引导并绊倒。当您执行像.Edit / .Post / .Delete这样的操作时,它们会将数据从TDataset复制到SQLite中,然后再返回,有时会失去对仍存在的数据和不存在的数据的跟踪...此外,还有一个商业Delphi本地的NexusDB组件。 - Arioch 'The

1

由于某些原因,这对我来说不起作用。我在设计时执行了CreateDataset,但它仍然会导致应用程序崩溃。这对我来说仍然是未知的。 一个警告。不要这样做:

XXXClientDataSet.Close;
XXXClientDataSet.Open;

因为它会报错。请使用而不是Open

xxxClientDataSet.CreateDataset;

在我的应用程序中,我需要重置数据并重新加载它,但这又导致了错误消息。

那么..我也遇到了同样的问题。那么正确的做法是什么呢? - Steve F

0

0

我的偏好是将数据集实际上作为XML进行管理。您可以使用设计工具创建基本结构,然后将其保存到磁盘。这样可以在可执行文件之外进行管理,编译为资源或在版本控制中单独管理。

以这种方式进行时,您可以使用LoadFromFile/Stream和Save变体。根据您的用途,请记得正确使用LogChanges和MergeChangeLog。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接