为啥CQRS Query端不使用ORM

Posted

技术标签:

【中文标题】为啥CQRS Query端不使用ORM【英文标题】:Why CQRS Query side does not use ORM为什么CQRS Query端不使用ORM 【发布时间】:2015-06-28 08:18:14 【问题描述】:

我从博客文章中阅读了 Greg Young 的文章。我看到 Query 正在从数据库中获取数据。我们使用查询 DTO 对象来填充 UI 屏幕。并建议使用包含普通 SQL 查询的薄层。不建议使用 ORM 工具,例如 Nhibernate 或 EF。因为他们使用延迟加载,所以在数据库上运行多个查询。

例如,我有一个 Order 屏幕。那应该是显示Order信息和Order line items。

public class OrderDto
   public string Name get; set;
   public string Date get; set;
   public IEnumerable<OrderLineItem> get; set;

要创建 OrderDto 实例,我应该向 Orders 表发送查询,然后向 OrderLines 表发送查询。我认为 ORM 工具会做同样的事情。那么为什么要使用纯 SQL 和新的 Thin Layer?

【问题讨论】:

我认为一次往返就足以获得订单和订单线。 【参考方案1】:

我不知道您所指的具体博客文章或引用,所以我无法直接解决。

然而,反对 ORM 的原因是许多项目将它用于查询和命令,使用相同的对象。因此,如果您使用 Order 对象进行保存(命令),然后当您想在屏幕上显示订单列表,并通过获取 Order 对象列表(查询)来实现,您可能不遵守CQRS 的基本原理。

另一方面,如果您使用 EF Order 对象进行保存,但使用 EF Linq 查询投影到 OrderDTO 列表上,我认为没有人会反对您使用 EF(或任何 ORM)。

【讨论】:

【参考方案2】:

“[...]因为他们使用延迟加载,所以在数据库上运行多个查询。[...]”。 嗯,不。你可以告诉你最喜欢的 ORM 不要使用延迟加载。在这种情况下,您很有可能会执行两个查询,这正是您在示例中指定的方式。 顺便说一句,关键是,因为您有两个单独的命令和查询模型,您不必强制使用 ORM 来查询数据存储,因此如果您想优化查询服务,则不应使用它。 相反,ORM 的好处在命令方面更为明显。

【讨论】:

【参考方案3】:

我不确定使用纯 SQL 背后的原因是什么,因为特定的博客文章未包含在问题中。

在您的示例中,您不需要两个不同的查询来获取订单和订单行。通常,您可以使用连接了两个表(order 和 orderline)的查询,NHibernate 也支持相同的查询。

当您使用像 NHibernate 这样的 ORM 时,它支持做得更好,借助 QueryOver / HQL 等功能,您可以直接填充 DTO,同时仅从数据库中获取所需的列。在这些情况下,延迟加载不起作用。

【讨论】:

以上是关于为啥CQRS Query端不使用ORM的主要内容,如果未能解决你的问题,请参考以下文章

命令查询职责分离模式(Command Query Responsibility Segregation,CQRS)

为啥 CQRS 存储库发布事件,而不是事件存储?

CQRS(Command and Query Responsibility Segregation)与EventSources实例

Command and Query Responsibility分离模式

Command and Query Responsibility分离模式

Command and Query Responsibility分离模式