CQRS 查询端实现

CQRS Query Side implementation

我有点困惑在哪里实现应用程序的查询端,atm 我有下一个架构:

Product.UI.Web.Admin (MVC)
Product.Application
 -CommandHandlers (e.g OrdersCommandHandler)
 -Commands (e.g CreateOrder)
Product.Domain
 -Model (Behavior-rich models / repository interfaces)
Product.Infrastructure (Base interfaces / classes)
Product.Persistence
 -ReadModel (EF Generated models)
 --Implementation (Repository implementations: FindByID / Save)
  1. 我应该将 Queries 命名空间放在 Product.Application 中并且它们应该从那里直接访问数据库吗? (UI <= Product.Application <= 数据库)
  2. 我应该创建新程序集 Product.Queries 并且 Product.UI.Web.Admin 应该直接访问它吗? (UI <= Product.Queries)
  3. 我是否应该在 Product.Application 中添加 Queries 命名空间并创建新程序集 Product.Reporting 并让应用程序程序集通过 Queries 命名空间使用 Reporting 程序集? (UI <= Product.Application.查询 <= Product.Reporting)

所有三个解决方案 return DTO 到 UI。

我正在考虑解决方案 #3,因为它可以很容易地在查询中使用 Domain Services 来构建结果,而且它将使用 Product.Reporting 作为 数据访问,可以使用ADO.Net、Entity Framework或NHibernate实现。或者我可能误解了什么。

请指点一下,帮我解决一下,谢谢

更新 我来到了第四个变种。

  1. 已创建 Product.Infrastructure.Queries 程序集,我有数据库 (dbcotnext) 和 ReadModel(EF 生成的模型和 通用查询接口 ) 命名空间。
  2. 在 Product.Application 中添加了 DataModel 命名空间,我有从 return 到 UI
  3. 的 DTO
  4. 在 Product.Application 中添加了 Queries 命名空间,在那里我实现了通用查询并使用 dbcontext 检索数据,映射到 DTO 并将 return 映射到 UI.

我想我只是在这里应用依赖倒置原则,并有类似 Application.Queries 的东西来定义接口和 Infrastructure.Queries 来实现这些接口。但是,我也看到了直接进入 Application 层的基础设施问题。例如,这就是 Vaughn Vernon 在 com.saasovation.collaboration.application.calendarCalendarEntryQueryService 的 SaasOvation 协作 BC 中所做的。

I am thinking about solution #3 as it will be easy to use Domain Services in Queries to build results and also it will use Product.Reporting as Data Access which can be implemented using ADO.Net, Entity Framework or NHibernate. Or maybe i misunderstood something.

是的,我也觉得你误会了什么。

首先让我们谈谈什么是域服务?: 当你有一个涉及多个实体的领域概念,但你 不确定哪个实体“拥有”该行为。它似乎不属于任何一种them.This思维模式是一种强大的 需要域服务的指标。 所以当你使用cqrs时,域服务存在于命令端,因此查询端无法访问域服务,实际上自然不需要域服务,因为查询端不执行任何业务logic.you 应该永远记住命令端和查询端是​​完全独立的。

CQRS 的另一个重要特征是 ReadModel 可以使用低级数据访问技术,如 ADO.Net 或微型 ORM,并通过士气低落的表进行查询以生成 reports.all 这个想法是为了提高性能 considerations.furthmore 随着系统未来的发展,您甚至可以在两个单独的实例上启动命令和查询端。