在几乎所有情况下,主键都不是您的业务领域的一部分。当然,您可能会拥有一些具有唯一索引的重要的面向用户的对象(UserName
针对用户或OrderNumber
订单),但是在大多数情况下,除了单个或多个值外,无需通过单个值或一组值公开标识域对象。管理用户。即使在那些特殊情况下,尤其是在使用全局唯一标识符(GUID)的情况下,您也会希望或希望使用备用键而不是公开主键本身。
因此,如果我对域驱动设计的理解是准确的,则不需要主键,因此也不必公开主键,这是很好的方法。他们很丑,使我的风格狭窄。但是,如果我们选择在域模型中不包括主键,则会产生以下结果:
- 天真的,仅从域模型组合中得出的数据传输对象(DTO)将没有主键
- 传入的DTO将没有主键
因此,可以肯定地说,如果您真的要保持纯洁并在域模型中消除主键,那么您应该准备能够根据该主键上的唯一索引来处理每个请求吗?
换句话说,在删除领域模型中的PK之后,下列哪种解决方案是处理识别特定对象的正确方法?
- 能够通过其他属性识别需要处理的对象
- 在DTO中获取主键;即,从持久性映射到域时消除PK,然后从域映射到DTO时重新组合PK?
编辑:让我们具体化。
说我的域模型VoIPProvider
,其中包括像场Name
,Description
,URL
,以及引用喜欢ProviderType
,PhysicalAddress
和Transactions
。
现在让我们说我想构建一个允许特权用户管理VoIPProvider
的Web服务。
在这种情况下,用户友好的ID可能没有用;毕竟,VoIP提供商是出于商业原因其名称在计算机意义上趋于不同甚至在人性意义上趋于不同的公司。因此,可以说一个唯一VoIPProvider
性完全由决定(Name, URL)
。因此,现在让我们说我需要一种方法,PUT api/providers/voip
以便特权用户可以更新VoIP
提供程序。他们发送一个VoIPProviderDTO
,其中包括的很多但不是全部字段VoIPProvider
,包括可能会展平的字段。但是,我看不懂他们的想法,他们仍然需要告诉我我们正在谈论的提供商。
看来我有2个(也许3个)选项:
- 在我的域模型中包含主键或备用键,并将其发送给DTO,反之亦然
- 通过唯一索引确定我们关注的提供商,例如
(Name, Url)
- 引入某种总是可以在持久层,域和DTO之间映射的中间对象,而不会暴露有关持久层的实现细节-例如,在从域到DTO并返回时引入内存中的临时标识符,