【发布时间】:2011-01-07 01:46:19
【问题描述】:
我有一个关于 DDD 和存储库模式的问题。
假设我有一个 Customer 聚合根的 Customer 存储库。 Get & Find 方法返回完全填充的聚合,其中包括地址等对象。一切都很好。但是当用户在 UI 中搜索客户时,我只需要一个聚合的“摘要”——只是一个带有摘要信息的平面对象。
我可以解决这个问题的一种方法是正常调用存储库上的 find 方法,然后在应用程序层中,将每个客户聚合映射到 CustomerSearchResult / CustomerInfo DTO,然后将它们发送回客户端。
但我的问题是性能;每个 Customer 聚合可能需要多个查询来填充所有关联。因此,如果我的搜索条件与 50 个客户匹配,那么对于可能检索我什至不需要的数据的数据库来说,这将是一个巨大的打击。
另一个问题是,我可能希望包含有关客户的汇总数据,这些数据超出了客户的聚合根边界,例如最后一次下订单的日期。 Order 有它自己的聚合,因此要获取客户的订单信息,我必须调用 OrderRepository,这也会降低性能。
所以现在我想我有两个选择:
向 CustomerRepository 添加一个额外的 Find 方法,该方法通过执行一个有效的查询返回这些摘要对象的列表。
创建一个专门构建的只读 CustomerInfoRepository,它只具有 1 中描述的查找方法。
但这两种感觉我都在违背 DDD 的原则。我的存储库继承自一个通用基础:Repository where T : IAggregateRoot。这些摘要信息对象不是聚合,并且与 T 的类型不同,因此 #1 确实违背了设计。
也许对于#2,我会创建一个没有 IAggregateRoot 约束的抽象 SearchRepository?
在我的领域中有很多类似的场景。
您将如何实施此方案?
谢谢, 戴夫
更新
阅读 Theo 的回答后,我想我会选择选项 #2,并在我的基础架构中创建一个专门针对这些场景的 SearchRepository。然后,应用层(WCF 服务)可以调用这些存储库,这些存储库直接填充摘要 DTO,而不是将域实体映射到 DTO。
**** 更新 2 ****
虽然我一年多前问过这个问题,但我想我只是补充一下,我已经发现了旨在解决这个确切问题的 CQRS。 Udi Dahan (http://www.udidahan.com/) 和 Greg Young (http://codebetter.com/gregyoung/) 写了很多关于它的文章。如果您使用 DDD 创建分布式应用程序,CQRS 适合您!
【问题讨论】:
标签: c# .net domain-driven-design repository-pattern ddd-repositories