在DDD中,如何使用多个存储库来执行只读列表

时间:2010-03-23 15:03:41

标签: repository domain-driven-design dto

如果您需要在页面上生成只读数据列表,并且该数据自然会来自多个(可能是5个或更多个不同的存储库),您会怎么做?

我们正在使用DDD并且已经强制通过存储库访问我们的数据库,但是有一种情况似乎不适合DDD,我们正在尝试决定使用的最佳模式。

例如,假设您有一个基于社区的网站,其中包含视频,论坛,博客等。您有一个包含评论列表的论坛页面。这很粗糙,但我希望这是有道理的。

<table>
<tr><td>User Name (with possible link)</td><td>User's community score.</td><td>User Avatar</td><td>User's E-mail</td><td>User's blog</td><td>User's videos</td></tr>
</table>
<table>
<tr><td>This is a comment.</td></tr>
</table>

因此,每条评论都包含几个不同的部分:用户名,社区分数,头像,电子邮件,用户博客和用户的视频页面。传统上,这些信息都来自不同的存储库。

问题在于效率。存储库可以最大化,但只能围绕其创建的聚合。当您需要访问位于多个存储库中的数据时,使用存储库对于读取访问来说效率低下。

我的解决方案是使用相关信息创建UserInformation DTO,并在UserForumsRepository中放置一个带签名的方法

ILIst<UserInformation> GetUserForumsUserInformationByForumPostID(int forumPostID).

我的一位同事建议以这种方式使用DTO打破了我们一直使用的设计模式,并建议更好的方法是获取论坛评论ID列表,然后将这些ID传递到各种存储库返回结果。

我自己的观点是,存储库的主要目的是封装对CRUD的CUD部分很重要的业务逻辑,但应该以最有意义的方式生成只读列表。如果合适的话,我认为从存储库中完全删除只读列表方法甚至是有意义的(例如,在跨多个不同类型页面使用的公共窗口小部件中)。

你如何处理这种情况?

2 个答案:

答案 0 :(得分:1)

我讨厌回答我自己的问题,但我没有任何评论,而且我似乎从通常的嫌疑人那里找到答案:福勒。

在我们的设计中,它与大多数简单的DDD相同,我们的应用程序直接连接到我们的存储库以获取和更新数据。但是,在更复杂的场景中,具体存储库和应用程序层之间还有一个额外的服务层。您可以传递DTO,而不是将对象从域模型传递到客户端。

根据Fower(PoEAA 401),您“......通常不能从域模型中传输对象,...因为对象通常连接在复杂的Web中,即使不是不可能,也很难序列化。 “ Fowler继续“相反,你必须从域对象传输简化形式的数据。”

实际上,特别是在分布式系统中,将DTO传递给客户端是常态。服务层如何从域层组装这些DTO应该对客户端不感兴趣。

我必须承认,我对Fowler的这句话感到有些不安。我非常喜欢在ASP.Net MVC中使用域模型的便利性。在创建主从细节UI设计模式视图时,它特别方便。当强类型视图与客户关联时,只需要一行代码就可以包含CustomerOrders.ascx局部视图(类型为IList)并将customer.Orders传递给局部视图。也许继续这样做是可以的,只要域对象是无行为的,但这是未来的问题。

答案 1 :(得分:1)

回答#2

这里需要的是具体存储库和客户端之间的额外服务层。有时,客户端需要的内容与存储库层提供的内容不同,尤其是在可以分发存储库的情况下。服务层允许您定义粗粒度方法并隐藏客户端的细粒度细节。使用服务层,您可以将轻量级DTO传递到客户端,而不是完整的业务对象。

要将业务对象映射到DTO,反之,工具Automapper正变得非常流行。