如何在添加子实体时避免持久化整个聚合根?

时间:2011-12-16 10:38:40

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

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

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集合,然后通过IAggregateRootRepository.AddOrUpdate()将其全部保存,从而添加到Children集合。然而,每当我添加一个子实体时,这将持续整个聚合根以及其大量的子集。如果我的存储库看起来像:

,我想我可以解决这个问题
public interface IAggregateRootRepository {
    public IAggregateRoot GetById(string id);

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

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

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

2 个答案:

答案 0 :(得分:5)

聚合根应该围绕写边界设计 - 也就是说,通常在单个批处理/事务中写入数据库的任何东西。如果您发现需要单独持久保存非根的子实体,则可能需要重新考虑您的设计,并使您的子实体成为一个独特的聚合根本身(因为它有一个单独的写边界)。

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

希望有所帮助:)

答案 1 :(得分:-1)

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

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