17

CQS 架构模式背后的原则是将查询和命令分成不同的路径。理想情况下,您的持久性存储可以读/写分区,但在我的情况下,有一个单一的规范化数据库。

如果您使用的是 ORM(在我的例子中是 NHibernate),很明显在发出命令时使用了 ORM。但是,您需要运行所有各种查询来为用户屏幕塑造数据 (DTO),在执行 CQS 的查询端时放弃 ORM 是否普遍做法?

我应该在哪里实现我的查询和 DTO 预测?直接 ADO.NET(数据读取器、dto、数据表、存储过程)?一些查询是非常独特的,并且涉及很多连接来将所有内容组合在一起。我不想为查询对数据库进行非规范化,但我可以创建视图(穷人的非规范化)。

4

5 回答 5

8

我假设 CQS 是指 DDD 架构模式,也就是CQRS,而不是严格意义上的传统CQS原则。

我仍然会为您的只读模型使用 NHibernate。有许多优点,例如未来和多查询、延迟/急切加载等......这将优化数据库的聊天性。此外,如果 UI 允许用户从本质上更改 where 子句,则使用 ORM 编写查询会更容易。

关于如何在技术上处理只读模型,您可以使用 NHibernate将实体标记为不可变。您可以简单地将所有读取模型实体标记为不可变。此外,我认为您不能更新 NHibernate 中的预测,因此这是作为只读模型的另一种选择(如果我错了,请纠正我,因为我不是 100% 确定)。

关于丑陋或不可能的 NH 映射:NH 可以映射到视图和存储过程,所以我认为在需要时使用它们会很好。对于只读方案,视图可能比存储过程更灵活一些,因为您的 SQL 仍然是动态的。但是,如果您需要对这些扁平结构中的任何一个进行读/写,我会映射到存储过程。

于 2009-08-18T23:20:54.713 回答
6

最终,这个想法是你应该使用任何使查询通道最容易构建和维护的东西。您不再需要担心更新、执行业务规则、维护数据完整性甚至处理负载(大部分情况下)。因此,您可以自由选择许多以前不在桌面上的选项。

但是 NHibernate 仍然是一个不错的选择……它不再是自动默认值(有时它是用于命令端的)。

我们选择使用 Castle Active Record(它基于 NHibernate 底层),主要是因为它有一个很好的特性,可以从一个类中为您生成一个表。这非常适合我们,因为这是我们的工作流程:首先,我们创建一个 ViewModel 类。这个类完全是为了视图的需要而设计的。然后,我们用 Castle Active Record 属性标记该 ViewModel。然后,我们要求 Active Record 在 Query 数据库中为该类生成相应的表。这是我们发现的快速获取服务于 ViewModel 类的 Query 数据库表的最快、最流畅的方法。自动生成反映了表存在的唯一原因是为视图服务的现实。

于 2010-03-07T23:17:55.533 回答
3

我们将 EF 用于命令部分,将直接 ADO.NET => DTO 用于查询链。好处:

1) 能够优化 SQL 查询并使用未抽象到 ORM 层的高级数据库存储功能

2) 更少的开销

但是我们仅将分离用于要求苛刻的部分(搜索),其余部分依赖于通用实体框架模型。

于 2010-01-12T11:48:38.113 回答
1

无需使用不同的方法来读取数据库与更新数据库。CQS 只是声明更新数据存储的命令应该与从数据存储读取状态的查询分开。

您仍然可以使用 NHibernate 从您的数据存储中读取数据,但您可能希望通过创建两个不同的类来封装您的数据访问以使其显而易见。一个类具有读取(查询)数据存储的方法,另一个类具有向数据存储发出命令(添加、更新、删除)的方法。

您要避免的是一种从数据库获取消息,然后在数据库中将消息标记为已读的方法。这应该是两个不同的方法调用。您不应更改状态并从同一方法返回值。

于 2009-08-18T18:53:09.373 回答
1

我喜欢将 ORM 的读写分开,所以我会使用(并且我会使用):

用于命令的Nhibernate - 精美地映射我的域模型

Dapper.net用于查询 - 精美地映射我的 DTO 并在查询过于复杂时提供灵活性。

他们是完美的一对,就像韩索罗和丘巴卡一样。

于 2016-01-21T21:36:05.653 回答