假设我有2个实体--Foo和Bar。 Foo是一个聚合根,包含Bar。据我了解,它应该是这样的:
public class Foo{
private readonly Bar Bar;
}
我想为用户提供从定义列表中选择Bars for Foos(并更改它)的功能。
如果存储库应该仅用于聚合根,则意味着Bar实体没有存储库。
这会导致问题 - 如果不引用Foo,就无法独立创建/更新Bar。
这是否意味着Bar应该拥有一个存储库,尽管没有Foo它没有意义?
答案 0 :(得分:17)
如果要从不与Foo关联的Bars列表中进行选择,则这不是聚合根。例如,如果没有订单,则无法获取OrderItem的列表,因此这是单个聚合根(订单),但您可以获取要分配给OrderItems的产品列表,因此Product不是订单聚合根的一部分。
请注意,虽然OrderItem是Order聚合根的一部分,但您仍然可以单独创建和更新它。但是,如果不参考Order,你就无法得到它。对于你的Bar来说,即使它是Foo的一部分,你也可以得到每个(Foo.Bars)并使用它,或者做Foo.AddBar(新的Bar())。但是如果你需要在没有Foo的情况下获得List,那么Bar不是Foo聚合的一部分。它是一个单独的实体。
嗯,这就是我在这里看DDD的方式,但我当然不是Eric Evans。
答案 1 :(得分:8)
拥有聚合根的原因是:
我的观点
如果您需要在没有Bar
的情况下选择Foo
个对象,请使用BarRepository
。
<强>可是... 强>
如果您更新Bar
,它会破坏其父Foo
的验证规则,该怎么办?如果发生这种情况,您应该通过其父Bar
访问Foo
。
但是,如果您需要访问一堆Bar
个对象(例如批处理作业或报告),并且知道 Foos
将无法获取破碎,继续通过BarRepository
访问它们。
请记住,聚合根可以由其他聚合根组成。您可能会发现Bar
本身就是一个聚合根,为您提供BarRepository
的理由:)
答案 2 :(得分:2)
你确定Bar需要成为一个实体吗?您是否需要跟踪它并在域中更改它?如果您可以将其视为值对象,我建议您从服务中获取它,然后将所选值对象“连接”到Foo实体。对于通过下拉列表的瞬间。