我有一个名为Account
的聚合根和一个名为Contact
的实体,可以通过根目录上的方法访问:Account.GetContactById(string id)
。通过存储库访问聚合根,因此从存储中获取帐户的数据访问逻辑就在那里。
访问Contact
实体的数据访问逻辑应该位于何处?我看到的大多数示例都会显示搜索内存中集合的Account.GetContactById
方法。就我而言,Account
可以引用数千个Contacts
,我不想将其预取到内存中。因此,如果在调用方法时需要访问数据存储,我是否可以在以下位置实现该访问:
Account.GetContactById
方法?这样可以直接访问存储库之外的存储,并引入一些紧密耦合。AccountRepository
,可以由Account
汇总调用吗?这似乎将Contact
实体直接暴露给存储库的任何其他用户,这违反了埃文斯的规则。ContactRepository
?在这种情况下,我有一个非聚合根的实体的存储库。答案 0 :(得分:0)
@plalx的评论指出了我正确的方向。我在这里发布我的决议作为帮助其他可能有同样类型问题的人的答案。
在阅读了Vernon关于建模聚合的几篇非常好的文章后(你可以找到文章here和here)我得出的结论是我让构图结构把我推向了一个糟糕的状态模型。仅仅因为Contact
与Account
相关并不足以将它们放在同一个聚合中。来自弗农:
设计聚合更多地是关于一致性边界。一个参考 两个聚合之间并不意味着它们具有相同的一致性 边界,因此是一个聚合,其中一个作为根。
他解释了这不会缩放,部分是因为我遇到的问题,使用sprint跟踪系统作为例子:
记住性能和可扩展性,当一个人发生时会发生什么 一个租户的用户想要将一个积压项添加到产品中, 一个已经很久了,已有数千个积压项目? 假设一个能够延迟加载的持久性机制(Hibernate)。我们 几乎从不加载所有积压项目,发布和冲刺 一旦。仍然有数以千计的积压项目被加载到内存中 只是为已经很大的集合添加一个新元素。
他提供了一些有用的评论,关于如何在可能的情况下优先选择具有值类型的单个实体聚合,而不是我正在构建的大型集群多实体聚合模型,并且单独的聚合应该仅通过标识符相互引用。他建议将应用程序服务作为解决聚合之间关联的一种方法。
因此,最后,我将Contact
和Account
分成不同的聚合,并使用应用程序服务来解析关联。