【问题标题】:Where to implement data access for an aggregate root entity accessor method在哪里为聚合根实体访问器方法实现数据访问
【发布时间】:2015-07-26 16:14:20
【问题描述】:

我有一个名为 Account 的聚合根和一个名为 Contact 的实体,可以通过根上的方法访问:Account.GetContactById(string id)。对聚合根的访问是通过存储库进行的,因此从存储中获取帐户的数据访问逻辑驻留在那里。

访问Contact 实体的数据访问逻辑应该驻留在哪里?我看到的大多数示例都会显示 Account.GetContactById 方法搜索内存中的集合。就我而言,Account 可以引用数千个 Contacts,我不想将它们预取到内存中。因此,鉴于调用该方法时需要访问数据存储,我是否在以下位置实现该访问:

  1. Account.GetContactById 方法?这将直接访问存储库之外的存储,并引入一些紧密耦合。
  2. AccountRepository,所以它可以被Account聚合调用?这似乎会将 Contact 实体直接暴露给存储库的任何其他用户,这违反了 Evans 的规则。
  3. 另一个存储库,例如ContactRepository?在这种情况下,我有一个不是聚合根的实体的存储库。
  4. 其他?

【问题讨论】:

  • 为什么Contact 不是它自己的聚合根?您为什么决定使用大型集群 Account 聚合?
  • @plalx 好点。我的困境可能只是一个糟糕的建模决定的产物。我会再考虑一下。
  • 通常,如果没有要强制执行的不变量,例如最大联系人数量等,那么 Contact 可能是一个 AR,因为通过将它们聚集在 Account 中您将一无所获。跨度>
  • @plalx 您的建议使我找到了正确的解决方案。我想给你一些信任,所以如果你想把它作为答案发布,我会接受它并用我的解决方案细节添加 cmets。

标签: domain-driven-design aggregateroot


【解决方案1】:

@plalx 的 cmets 为我指明了正确的方向。我在此处发布我的解决方案,以帮助可能有此类问题的其他人。

在阅读了 Vernon 撰写的几篇关于建模聚合的非常好的文章(您可以找到文章 herehere)之后,我得出的结论是,我让组合结构将我推向了一个糟糕的模型。仅仅因为 ContactAccount 相关并不足以将它们放在同一个聚合中。来自弗农:

设计聚合更多的是关于一致性边界。参考 两个聚合之间并不意味着它们具有相同的一致性 边界,因此是以一个为根的单个聚合。

他以冲刺跟踪系统为例解释了这无法扩展,部分原因是我遇到的问题:

牢记性能和可扩展性,当一个 一个租户的用户想要将单个积压项目添加到产品中, 一个已经有多年历史并且已经有数千个积压项目的设备? 假设一个能够延迟加载(休眠)的持久性机制。我们 几乎从不加载所有积压项目、发布和冲刺 一次。尽管如此,成千上万的积压项目仍将加载到内存中 只是为已经很大的集合添加一个新元素。

他就如何在可能的情况下首选具有值类型的单个实体聚合而不是我正在构建的大型集群多实体聚合模型提出了一些有用的建议,并且单独的聚合应该仅通过标识符相互引用。他建议将应用程序服务作为解决聚合之间关联的一种手段。

所以,最后,我将ContactAccount 分离到不同的聚合中,并使用应用服务来解决关联。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    相关资源
    最近更新 更多