【问题标题】:How to avoid persisting entire aggregate root when adding child entity?添加子实体时如何避免保留整个聚合根?
【发布时间】:2012-01-21 21:47:48
【问题描述】:

我有一个带有聚合根的域模型:

public interface IAggregateRoot {
    public string Id { get; }

    public string Foo { get; set; }
    public int Bar { get; set; }

    public IList<IChildEntity> Children { get; }
}

Children 集合往往会变得非常大,当通过 IAggregateRootRepository 检索 IAggregateRoot 实例时,我将延迟加载它。我的问题是这个;如果我想将 IChildEntity 添加到 IAggregateRoot 的 Children 集合中,我的存储库如何让我避免持久化整个聚合?

例如,假设我的 IAggregateRootRepository 如下所示:

public interface IAggregateRootRepository {
    public IAggregateRoot GetById(string id);

    public void AddOrUpdate(IAggregateRoot root);
}

然后我可以通过 IAggregateRootRepository.GetById() 获取 IAggregateRoot 实例来添加到 Children 集合,将子项添加到 Children 集合,然后通过 IAggregateRootRepository.AddOrUpdate() 将其全部持久化。但是,每次我添加一个子实体时,这都会保留整个聚合根及其大量子元素。如果我的存储库看起来像这样,我想我可以解决这个问题:

public interface IAggregateRootRepository {
    public IAggregateRoot GetById(string id);

    public void AddOrUpdate(IAggregateRoot root);
    public void AddOrUpdate(IChildEntity child);
}

但是,正如我所理解的存储库模式,存储库应该只处理聚合根,上面的解决方案肯定会打破这个要求。

还有其他更好的方法来避免这个问题吗?

【问题讨论】:

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


    【解决方案1】:

    聚合根应围绕写入边界设计 - 即通常在单个批处理/事务中写入数据库的任何内容。如果您发现需要单独保留不是根的子实体,则可能是时候重新考虑您的设计,并使您的子实体本身成为一个不同的聚合根(因为它具有单独的写入边界)。

    您的原始聚合根将不包含子实体,而是对它们的引用(因为它们现在本身就是聚合根 - 聚合根之间的链接应该通过引用键)。这也有助于您的延迟加载策略。

    希望有帮助:)

    【讨论】:

    • 获取孩子列表怎么样?是原来的 AggregateRootRepository 还是新的 ChildAggregateRepositroy 的工作?或者这是否意味着子集合现在需要知道如何将自己加载到父实体中?
    【解决方案2】:

    通常,ORM 负责数据库中整个聚合的更新。它检测在检索到的实体中所做的更改,并且只会保留聚合的修改后的实体。

    因此,如果您只将一个子项添加到根目录,并且您在聚合中没有其他修改。然后 ORM 将只为子实体插入一条新记录,而将根聚合和其他子记录单独保留。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-19
      • 2013-05-31
      • 1970-01-01
      • 2022-10-13
      相关资源
      最近更新 更多