使用自然键作为DomainObject或GUID的ID +自动增量域驱动设计

Jai*_*cap 5 orm database-design domain-driven-design primary-key-design

我已经阅读了很多有关DDD的文章,并且注意到大多数文章在持久化到数据库时都使用GUID作为其ID。他们说GUID可以很好地扩展,并且在可伸缩性方面,自动递增ID是一个很大的禁忌。

我现在困惑是使用GUID还是auto-increment

基本上,域是关于 membership system (binary tree). (tracking of register members)

第一个要求是我们应该有一些东西可以在系统中唯一地标识它们(我们称之为7位Account No.)。

然后新的Members可以被另一个注册Member。我们称其为推荐人。

现在,Im计划做的是将MemberIdGUID类型作为DomainObject Id,在其中它用作将用于连接的主键,外键(在Referral上,referer_id将是GUID MemberId)。AccountNo将是一个自动增加的列,或者可能是通过MAX()+ 1从存储库中获取的。主要用于系统和链接中的搜索功能。

自从只是技术上的实现以来,DomainObject的ID是否应该对系统用户保持隐藏状态?

可以将两者结合起来吗?GUID作为数据库中的row_id(代理键)。和(自然键)自动递增?

是否可以AccountNo从构造函数中排除,因为它还是会自动递增的?强制不变量怎么办?那么从存储库中获取下一个ID的方法是否可以包含AccountNo在构造函数中?

我是否应该只使用自动增量ID并忘记GUID,删除MemberId并让它AccountNo成为DomainObject的ID?

注意:

我不是要建立下一个facebook。

我只想练习DDD的战术方面,以了解如何在了解其利弊的基础上做出艰难的架构决策。

我只想练习DDD的战略性一面,以了解如何在了解PROS和CONS及其实施情况的基础上做出艰难的架构决策。

如果我们用会员注册来制作3种情况:

  • 第一种情况:会员注册每分钟发生一次。
  • 第二种情况:成员注册每小时发生一次。
  • 第三种情况:会员注册至少每天进行5次。

它将如何影响决策?

技术栈:

  • ASP MVC 5
  • SQL Server 2014
  • C#
  • 精巧的ORM

the*_*Dmi 5

你的问题可能有太多的问题,无法给你一个完整的答案,因为ID设计并不简单,有很多方面。我可以推荐 Vaughn Vernon 的书“Implementing DDD”,它有一个专门讨论身份设计的部分(第 5 章“实体”- 唯一身份)。

无论如何,我会尽力为您指出正确的方向,而无需背诵该章中的所有内容:-)。

你需要什么?

您已经提出了一些有关 ID 设计的问题,但还有更多问题需要询问。只有这样,您才能决定 GUID、DB 生成的 ID 还是不同的 ID 是否合适。

  • ID 的域意义是什么?也许 ID 只是为了方便技术解决方案而存在,但根本不是域的一部分?
  • 谁提供身份证?这可以是用户、应用程序、数据库甚至另一个有界上下文。
  • 什么时候需要身份证?在创建关联实体之前、创建时还是仅在实体持久化时?

这些问题的答案将限制您可以使用的 ID 生成类型。

您应该注意什么

关于 ID 设计有一些规则。强烈建议您遵循这些建议,以免以后搬起石头砸自己的脚:

  • 确保您的 ID 是唯一的。对于用户提供的 ID,这尤其值得关注。您需要强制执行唯一性并让您的用户能够检测现有 ID。对于应用程序生成的随机 ID 或数据库生成的 ID,这通常不是问题。
  • 确保您的 ID 稳定。永远不要更改实体的 ID!毕竟,ID 是用来引用实体的。这样做的结果是,您不应该将可能更改的内容作为您的 ID 的一部分。例如,一个人的姓氏可能不是一个好的选择,因为当某人结婚时,姓氏可能会改变(并且由于非唯一性,这也可能是有问题的)。
  • 如果 ID 只是一个技术概念,则隐藏它们。从 DDD 的角度来看,将技术概念作为领域模型的一部分是错误的。

例子

以下是如何找到 ID 设计的示例:

允许稍后创建ID(即通过持久性)意味着您在刚创建实体时确实有一个没有ID的实体。因此,如果您需要早期或即时 ID,则不能使用数据库生成的 ID(除非您接受仅联系数据库进行 ID 检索)。

然后您可能会认为用户对该 ID 不感兴趣,因此必须指定 ID 会很奇怪。这留下了应用程序生成的 ID。

对于应用程序生成的 ID,您需要确保 ID 是唯一的。这对于单实例应用程序来说是微不足道的,但一旦您使用多个应用程序实例创建负载平衡设置,问题可能会更大。这就是为什么许多人首先使用随机ID(例如GUID)的原因,这样他们在扩展时就不会陷入死胡同。

如您所见,此示例做出了许多假设。没有对错之分,但有了上述问题,您应该能够做出明智的决定。


Mik*_*eSW 5

我只是想练习 DDD 的战术方面,以了解如何在了解其优缺点的情况下做出艰难的架构决策。

你错了。你无法通过实践战术来学习战略。战术是实施战略的方法 。但你首先需要一个策略。

不管怎样,关于你的问题,它很简单:使用 Guid。它有2个优点

  1. 全局标识符
  2. 可以从应用程序轻松生成。自动递增的 id 意味着复杂的服务或对数据库的依赖。不要让你的生活变得复杂。

也应该使用自然 ID,例如 AccountNo。然而,该指南是出于技术目的而存在的。自然键格式将来可能会发生变化,Guid可以轻松支持自然键多种格式。

作为一种实践,最好将您的实体 id 设为值对象(即使它只是 Guid)。您也可以将 guid 合并进去AccountNo,VO 不需要只有一个值。例如,在我当前的应用程序中,我有一个ProjectId(Guid organization,Guid idValue)ProjectAssetId(Guid organization,Guid projectId,Guid idValue)