Delphi中是否有某种方法可以同时缓存主 - 详细信息行并发布主数据行和详细子行

War*_* P 8 delphi ado master-detail

我想在内存中发布一些子行,然后有条件地发布它们,或者不将它们发布到底层SQL数据库,具体取决于父行是否已发布或未发布.我不需要完整的ORM,但可能就是这样:

  1. 用户点击添加医生.添加医生对话框打开.
  2. 在"添加医生"中单击"确定"之前,在"添加医生"对话框中,用户会添加一个或多个仅存储在内存中的患者.
  3. 用户在添加医生窗口中单击确定.现在所有患者都被储存,再加上新医生.
  4. 如果用户在医生窗口上单击取消,则丢弃所有医生和患者信息.

尝试从心理上考虑如何使用delphi数据感知控件和TADOQuery或其他ADO对象来完成上述操作.如果有一种非ADO特定的方法,我也对此感兴趣,我只是把ADO扔到那里因为我碰巧在我当前的应用程序中使用MS-SQL Server和ADO.

因此,在我之前工作了很短时间的雇主中,他们有一个TMasterDetail专门编写的课程,用于将上述内容添加到ADO记录集中.它有时会起作用,有时候会失败一些非常有趣且难以修复的方法.

是否有任何内置于VCL中的内容,或任何具有执行此技术的强大方法的第三方组件?如果没有,我正在谈论上面要求ORM?我认为ORM被很多人认为是"坏",但上面是一个非常自然的UI模式,可能会出现在一百万个应用程序中.如果我使用非ADO非Delphi-db-dataset工作方式,上面几乎不会出现我可能编写的任何持久层中的问题,但是当主键使用标识值链接时主人和细节行进入画面,事情变得复杂.

更新:在这种情况下,交易并不理想.(提交/回滚对我来说太粗糙了.)

Ken*_*ran 3

您问两个不同的问题:

  1. 如何缓存更新?
  2. 如何同时提交对相关表的更新。

缓存更新可以通过多种不同的方式完成。哪一种最好取决于您的具体情况:

ADO 批量更新

由于您已经声明您正在使用 ADO 访问数据,因此这是一个合理的选择。在打开数据集之前,您只需将 LockType 设置为ltBatchOptimistic,将 CursorType 设置为ctKeySetctStatic 。然后,当您准备好提交时,调用 TADOCustomDataset.UpdateBatch。

注意:底层 OLEDB 提供程序必须支持批量更新才能利用此功能。SQL Server 的提供程序完全支持这一点。

据我所知,除了在两个数据集上按顺序调用 UpdateBatch 之外,没有其他方法可以在持久化数据时强制执行主/详细信息关系。

Parent.UpdateBatch;
Child.UpdateBatch;
Run Code Online (Sandbox Code Playgroud)

客户端数据集

数据缓存是 存在的主要原因之一TClientDataset,同步主/详细信息关系一点也不困难。

为了实现此目的,您可以照常在两个数据集组件上定义主/详细信息关系(在您的情况下ADOQueryADOTable)。然后创建一个提供程序并将其连接到数据集。将单个 TClientDataset连接到提供商即可完成。TClientDatset将详细数据集解释为嵌套数据集字段,可以像任何其他数据集一样访问该字段并将其绑定到数据感知控件。

一旦完成,您只需调用TClientDataset.ApplyUpdates,客户端数据集将负责正确排序主/详细数据的更新。

ORM

关于 ORM 有很多可说的。StackOverflow 上的答案太多了,所以我会尽量简短。

ORM 最近名声不佳。一些专家甚至将它们标记为反模式。我个人认为这有点不公平。对象关系映射是一个很难正确解决的问题。ORM 试图通过抽象出在关系表和对象实例之间传输数据所涉及的大量复杂性来提供帮助。但与软件开发中的其他一切一样,没有灵丹妙药,ORM 也不例外。

对于没有大量业务规则的简单数据输入应用程序,ORM 可能有点大材小用。但随着应用程序变得越来越复杂,ORM 开始看起来更有吸引力。

在大多数情况下,您需要使用第三方 ORM,而不是自己开发。编写一个完全符合您的要求的自定义 ORM 听起来是个好主意,并且很容易从简单的映射开始,但您很快就会开始遇到诸如父/子关系、继承、缓存和缓存失效等问题(相信我,我知道这一点)根据经验)。第三方 ORM 已经遇到了这些问题,并花费了大量资源来解决它们。

对于许多 ORM,您可以用代码复杂性来换取配置复杂性。他们中的大多数人正在积极致力于通过公约和政策来减少样板配置。如果您命名所有主键Id,而不必将每个表的Id列映射到每个类的相应Id属性,您只需告诉 ORM 有关此约定,并且它假定它知道的所有表和类都遵循该约定。您只需在不适用的特定情况下覆盖该约定。我不熟悉 Delphi 的所有 ORM,所以我不能说哪些支持这个,哪些不支持。

在任何情况下,您都需要设计您的应用程序架构,以便您可以尽可能推迟决定使用哪个 ORM 框架(或任何框架)。