c# - 持久性 ID 和域模型实体

标签 c# persistence domain-driven-design repository-pattern

我很好奇人们对将 DAL 实体的 ID 保留为域实体的属性,最多只读属性的想法。

我的第一个想法是这样做没问题,但我越想越不喜欢这个想法。毕竟域模型应该完全不知道数据是如何持久化的,并且在每个域模型上保留和 Id 属性是一个不太微妙的指示。持久层可能不需要主键,或者域模型中公开的另一个属性可能是识别的合适候选者,模型编号。也许吧。

但这让我开始思考,对于没有可靠方法唯一标识数据库持久层条目的域模型,在更新或删除时它们如何标识条目?

基于弱引用键的字典可以解决问题; WeakDictionary<DomainEntity, PrimaryKeyType> .每当存储库的客户端获取 DomainEntity 的集合时,该字典将成为存储库实现的一部分。对实体及其持久层 Id 的弱引用存储在这个内部字典中,这样当需要将修改后的实体返回到存储库以更新持久层时,可以执行以下操作来取回 Id

PrimaryKeyType id = default(PrimaryKeyType);
if (!weakDictionary.TryGetValue(someDomainEntity, out id))
     // id not found, throw exception? custom or otherwise..

// id found, continue happily mapping domain model back to data model.

在我看来,这种方法的好处是域实体不需要维护其持久层特定的 id,并且存储库强制您通过调用 Fetch... 获得合法的域实体。方法或 Add/CreateNew方法,否则如果您尝试更新/删除实体,它将抛出异常。

我知道这可能是过度设计,我应该冷静下来并务实一点,我只是想知道其他人对此有何看法。


我不想为这个小问题再开一个帖子,因为它有些相关。但由于是最近我才开始研究 DDD(虽然在这种情况下我的数据库排在第一位)我想知道我是否可以确认我对领域实体有正确的心态,这是我的员工领域实体的一个缩减示例。

public class Employee : DomainEntity
{
    public string FirstName { get; }
    public string LastName { get; }
    public UserGroup Group { get; }
    // etc..


    // only construct valid employees
    public Employee(string firstName, string lastName, SecureString password, UserGroup group);

    // validate, update. (not sure about this one.. pulled it 
    // from an open source project, I think that names should be able to be set individually).
    AssignName(string firstName, string lastName);

    // validate, update.
    ResetPassword(SecureString oldPassword, SecureString newPassword);

    // etc..
}

谢谢!

最佳答案

您关于使用弱引用的提议存在一个重大缺陷。

您可能知道,领域实体的一个重要特征是它们必须具有身份。这对于比较原因很重要。如果两个实体具有相同的身份,无论它们的属性值如何,那么它们都被认为是相等的:

Entity1 == Entity2 ⇔ Entity1.Identity == Entity2.Identity

典型的“设计模式”是从 DomainEntity<T> 继承所有实体抽象类,它覆盖了这些对象的比较并通过身份进行比较。

现在,考虑使用弱引用查找的方法。让我们举个例子:

你获取一个 Entity1 ,从存储库中说“Reegan Layzell”用户。然后您再次从存储库中获取完全相同的“Reegan Layzell”实体作为 Entity2 .您现在在域中的两个对象中拥有相同的实体。但是他们有不同的引用(当然)。

比较时,这些实体在您的域中不会被视为相等。

我很佩服您害怕将数据库问题引入您的域模型,但是将数据库 ID 传播到您的实体中几乎不会影响模型的质量,而且会为您省去很多麻烦.就像你说的,我们需要务实。

关于您的 Employee示例:是否 AssignName真的有意义吗?现实中,员工的姓名真的可以在创建后更改吗?除此之外,看起来你的想法是正确的。我强烈建议你看这个:Crafting Wicked Domain Models作者:吉米博加德。

关于c# - 持久性 ID 和域模型实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23419358/

相关文章:

c# - 如何将事件传递给方法?

c# - 在 Javascript 中访问 C# 函数

c# - 如何编码可变大小的结构数组? C# 和 C++ 互操作帮助

java - 实体未使用 EclipseLink 进行持久化

ios - 小型数据库的方法 - iOS

php - 实体、存储库和组合 - 依赖注入(inject)

c# - WinForms中控件和窗体拉伸(stretch)的处理方法

java - 对子类使用 JPA 2.0 @Inheritance 注释是否有意义?

c# - 避免域模型中的循环引用

ruby-on-rails - 在 CQRS 和 DDD 流程中创建值对象的位置