如何从存储库中获取实体对象的ID

问题描述 投票:0回答:2

在DDD中,当我从存储库中获取实体时,如何为Id属性添加水合物?当我第一次创建实体时(在持久性之前),我可以在实体的构造函数中生成唯一的ID,但是当我从存储库中获取项目时,我已经有一个ID!那我该如何设置呢?将ID传递给实体的构造函数只是感觉不正确,或者也许是吧?

我没有使用ORM。

public interface IPersonRepository
{
    Person GetById(long id);
}

public abstract class Entity
{
   public long Id { get; private set; }

   protected Entity()
   {
      Id = // Generate a unique Id with some algorithm.
   }
}

public sealed class Person : Entity
{
   //...
}
c# entity domain-driven-design repository-pattern ddd-repositories
2个回答
1
投票

当我第一次创建实体时(在持久性之前),我可以在实体的构造函数中生成唯一的ID ...

这可能不是一个好主意。非确定性数据(例如时间或远程可变状态的副本)应输入到域模型中。在实践中,您经常会逃脱它。但这本身并不能使它成为一个好主意。

通常的答案是,存储库将获取信息的持久表示形式(例如,DTO),并将其交给目的是构建实体的factory

因此,实体的身份只是从存储库传递到工厂的另一条信息。

现在,“工厂”只是另一个生命周期模式;它可以采用许多不同的形式,包括构造函数的形式。在这种情况下,标识符通常只是作为参数传递给实体。

尤其是标识符可能有点怪异,因为它们通常不表达业务语义。标识符模式的典型特征是它们实际上是不透明的,仅支持相等比较。您的实体几乎永远不会查看自己的标识符来弄清楚下一步该怎么做。

但是如果您的实体需要引用其自身的标识符,则无论出于何种原因,通常在初始化对象时都会创建该引用,并且从此以后一直保持不变(换句话说,实体标识符属性是一个对不可变值的不可变引用)。


0
投票

1)聚合还是实体?我认为您在DDD方面的问题有些困惑。通常,您不应该加载实体。您应该通过聚合根(实体)来加载聚合,该聚合的所有其他实体都应自动加载。

来自Evans DDD:

仅AGGREGATE根可以直接通过数据库查询获得。所有其他对象必须通过关联遍历找到。

Martin Fowler

聚合是数据存储传输的基本元素-您请求加载或保存整个聚合。

Aggregate Root

2)如何设置ID。]使用不可变属性是个好主意。 public long Id { get; private set; },让我们以为使用不可变ID时我们做的正确。现在,让我们继续并找到正确设置ID的可能方法。

  1. 通过类方法设置ID。看起来为现有实体(聚合根)设置ID令人困惑。我不建议使用此选项。
  2. 构造函数的ID。

  3. 为什么不呢?您可以在创建实体(聚合根)期间设置ID。从Evans DDD:

    公共构造函数必须遵循与工厂相同的规则:它必须是满足所创建对象所有不变量的原子操作。

  4. 工厂。>>来自Evans DDD:

  5. 特别是AGGREGATES的复杂程序集要求工厂

  6. 反序列化过程中的设置ID。

  7. 清晰简单。我会选择这个。我将ID和其他数据存储在一起(it's common practise)。 GetById(long id);返回在反序列化期间已经设置了PersonId
© www.soinside.com 2019 - 2024. All rights reserved.