我们应该在持久化域模型时使用外键约束吗?

Sau*_*lva 7 language-agnostic orm design-patterns domain-model

不久前,我与同事讨论了域模型的持久性以及是否应该在数据库级别强制执行外键约束.

我的第一反应是关系数据库的使用意味着强制执行这些约束,但有些人认为数据库应该只被视为持久性机制,因此我们应该避免在其中放置任何业务逻辑.我们最终没有使用外键约束.

这是我的问题(我希望它不太通用):在这些案例中强制执行关键约束是否被视为良好做法?

van*_*van 9

实施约束,但不要在业务逻辑中依赖它们

  • 数据库上没有业务逻辑:我同意这个原则.如果您的非SQL业务代码依赖于数据库约束来检查数据库的一致性,那么您应该重新考虑您的业务逻辑.
  • 除了业务逻辑之外,还有数据库约束没有错.特别是因为使用FOREIGN KEY和其他UNIQUE约束之类的参照完整性很容易做到,而且RDBMS非常有效地为您完成这项工作而无需太多维护.
  • 你也不会在数据库上使用索引,因为它不是纯粹的持久性相关吗?
  • 找到并修复软件错误可能需要一些时间,但你肯定不想花更多时间清理或者(更糟)丢失一些数据,只是因为你为自己省去了为FK编写单行脚本的麻烦.真的:你在这里免费获得一些东西并拒绝它吗?
  • [EDIT-1]:您能保证数据库中的数据只能通过您的应用程序进行管理吗?似乎总是存在异常,主要是高级用户,他们有时(非常罕见:-)犯错误并执行一些SQL语句来清理代码,更新状态(由于拼写错误导致无效值)等.
  • [编辑2]:构建域驱动模型不是聘请优秀数据库管理员的借口.使用ORM不是聘请优秀DB开发人员的借口.

但是,如果您和您的团队能够编写无错误的软件并处理代码中的所有可能的异常情况(包括硬件/网络/虚拟用户/程序员错误失败),那么"Hei,为什么还要为冗余的 FK约束而烦恼" . ......" - - 激光 -


Chr*_*eis 7

我认为是这样,我认为它不是业务逻辑的一部分,而是防止"坏"数据被输入数据库.一旦数据库变得非常大,这些约束将防止将来出现令人头疼的问题.

当您有多个开发人员针对相同数据开发应用程序时,这将特别生效.这将确保他们也只能输入有效数据.将约束控制在1个点而不是x应用程序中肯定是有益的.


Mic*_*art 5

如果您想遵循领域驱动设计范例,那么对于聚合内的任何内容,答案都是“是”,而对于任何跨聚合链接,答案都是“否”。

几乎在所有情况下,您都希望在删除根本身时删除聚合根下的所有内容,因此使用表示此情况的外键以及级联删除,可以让您在数据库级别实现此目的。如果您不想在数据库级别执行级联删除,您也可以让存储库自行执行级联删除,但要点仍然是,如果没有根,聚合子级就不应该存在。

对于跨聚合问题,您可能需要处理业务决策,以确定删除其中一个或另一个后会发生什么。通常,您会希望异步处理此问题以实现可扩展性,因此您的域模型最终会保持一致。因此,在这些情况下强制执行外键是没有意义的,因为在一段时间内一个或另一个键可能不存在。

希望有帮助!要了解更多信息,请务必查看埃文斯关于领域驱动设计的书- 以及网络上的许多链接。