在领域驱动设计中,将GUID作为标识字段是否更好?

7
使用GUID作为标识字段,相比自增整数,是否更容易实现领域驱动设计?使用GUID可以避免跳转到数据库以获取实际值。

在我看来,实体的标识符和数据库中的主键是互斥的概念。PK 是一种实现细节;领域不应该依赖于持久层或了解它。如果您接受这一点,那么所选答案中的一个观点就更有意义了。实体标识符可以是领域设置的 GUID,而 PK 可以是自动递增的整数。 - Sinaesthetic
1
在抽象化持久化实现方面,问问自己:如果你要将数据库切换到平面文件存储,你能从平面文件中获取ID吗?如果你的答案是否定的,那么你就可以理解为什么不应该使用它。通过允许领域设置实体的标识符(在本例中为guid),您可以将该概念保留给领域。让数据库也生成一个主键(在本例中为int),可以对其进行索引;这又是一个实现细节。 - Sinaesthetic
6个回答

8

嗯,GUID很容易,并且看起来是最合适的选择。对于前端程序员来说,它们很诱人,因为他们不必处理数据库。

另一方面,当没有考虑太多数据库问题时使用时,它们可能存在潜在缺点。因此,我会尽可能地警告您不要使用它们。

真正的问题是:在实体存储到数据库之前,您是否真的需要知道实体的ID?真的吗?为什么?

如果最终决定使用GUID,并且使用SQL Server作为您的数据库后端(我不了解其他RDBMS足以做出明智的建议),我强烈建议您确保GUID被用作表上的聚集键。这将影响性能-毫无疑问。

如果您将GUID用作主键,请确保使用其他某些列而不是GUID作为聚集键,以减少对数据库的影响。例如,使用INT IDENTITY作为聚集键是我的首选。

请查看Kimberly Tripp撰写的这些文章,了解为什么在SQL Server数据库中,GUID绝对是聚集键的好选择-她是索引和性能问题方面的终极专家,她可以比我更好地阐述这些观点:

Marc


2
我认为重点不在于“在存储之前知道ID”,而是领域应该设置ID作为实体的标识符,因为实体的标识符应该是领域关注的内容。PK是数据库的实现细节,领域对此一无所知。一个简单的递增整数ID就像数据库中的标识一样,这只是巧合。我认为这两个概念在DDD中需要保持分离。 - Sinaesthetic
2
如果我在同一个事务中发布事件消息,我可能需要引用聚合根的身份。 - pnschofield

6

领域驱动设计的核心原则之一是持久化无关性。因此,使用GUID可以为对象提供唯一标识而不必依赖于持久性存储,是最简单的方法。

注意:如果你担心使用GUID会影响数据库性能,请考虑使用COMB(特别是针对SQL Server索引碎片化的情况)。


2

我建议使用Guids,因为这样就没有混淆你正在查看的内容。此外,虽然这经常被拿来开玩笑,但我曾经调试过一个系统问题,它在寻找uint而不是guids。这导致了sharepoint中的一个模板被停用,并且没有办法重新激活它。花了2天时间才发现底层问题所在。所以,总之选择Guid's。


2
我认为GUID相对于递增整数的唯一优势在于身份创建的去中心化。即,递增整数需要原子递增和读取共享值,而GUID可以独立创建,几乎不会发生冲突。
至于你提到GUID允许在不查询数据库的情况下解引用实体的建议,除非问题中未提及其他信息,否则我不明白这是怎么回事。在这里,你的选择是关于键的类型,而不是是否使用键。如果你手头有一个键,并且该键通过数据库映射到一个值或实体,那么你需要查询数据库以解引用该键。

2

我使用guid的原因有两个:

  • ID不仅在创建上下文中是唯一的,因此可以在不同位置生成相同类型数据的ID。这在你有几个地理位置分布的安装程序彼此交换数据或在断开连接的情况下非常有用。
  • 它抵消了以逻辑方式处理ID的冲动,而是强制开发人员将值视为“只是ID”。

然而,我不一定会说这些论点仅适用于领域驱动设计。


1
不,绝对不是。GUID是一个实现细节,不应该泄漏到您的领域中。您需要一个身份值对象,我不关心您如何实现它。

我认为这完全是相反的。GUID是实现细节的完全相反;PK将是实现细节。在DDD中多次指出,实体的标识符应该是全局唯一标识符。无论是否将其用作数据库中的PK都是另一回事。 - Sinaesthetic
如果 @Sinaesthetic 认为身份识别不是一个相关的领域概念,那么最好再考虑一下。身份识别的实现并不是简单的。 - Stephan Eggermont
1
我甚至不确定那是什么意思。标识符应该是领域专家想要的任何东西;无论它是guid、int还是string都不重要。唯一不应该出现的是任何将其与数据库绑定的内容,例如自增的int,因为数据库是实现细节。guid只是一个值,而不是实现细节。 - Sinaesthetic
1
此外,在您的领域中,您将需要一个实体对象,而不是值对象。在实体对象中,您将拥有标识符,这就是 OP 所询问的内容。 - Sinaesthetic

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