CQS架构模式背后的原则是您将查询和命令分成不同的路径。理想情况下,您的持久性存储可以进行读/写分区,但在我的情况下,有一个规范化的数据库。
如果您使用的是ORM(在我的情况下是NHibernate),很明显在发出命令时会使用ORM。但是,在为用户屏幕设置数据(DTO)时需要运行的各种查询怎么样呢?在执行CQS的查询端时,通常会抛弃ORM吗?
我应该在哪里实施查询和DTO预测?直接ADO.NET(datareaders,dtos,datatables,stored procs)?有些查询非常独特,需要很多连接来将所有内容组合在一起。我不想为查询反规范化数据库,但我可以创建视图(穷人的非规范化)。
答案 0 :(得分:8)
我假设CQS你的意思是DDD架构模式又名CQRS,而不是传统的CQS原则。
我仍然使用NHibernate作为只读模型。有许多优点,例如未来和多查询,懒惰/急切加载等......将优化DB chattiness。此外,如果UI允许用户实质上更改where子句,则使用ORM组合查询会更容易。
关于如何在技术上处理只读模型,您可以使用NHibernate标记实体immutable。您可以简单地将所有读取的模型实体标记为不可变。此外,我认为你不能更新NHibernate中的预测,这是另一种选择,作为你的只读模型(如果我错了,请纠正我,因为我不是100%肯定)。
关于丑陋或不可能的NH映射:NH可以映射到视图和存储过程,所以我认为在需要时使用它们会很好。对于只读方案,视图可能比存储过程更灵活,因为您的SQL仍然是动态的。但是,如果您需要读取/写入任何这些扁平化结构,我将映射到存储过程。
答案 1 :(得分:6)
最终,我们的想法是你应该使用任何使查询通道最容易构建和维护的东西。您不再需要担心更新,执行业务规则,维护数据完整性,甚至处理负载(大多数情况下)。因此,您可以自由选择之前未提供的许多选项。
但是NHibernate仍然是一个不错的选择...它不再是自动默认值(有时它也适用于Command端)。
我们选择使用Castle Active Record(它基于NHibernate),主要是因为它有一个很好的功能,可以从一个类为你生成一个表。这非常适合我们,因为这是我们的工作流程:首先,我们创建一个ViewModel类。这个类完全是为了View的需要而设计的。然后,我们使用Castle Active Record属性标记ViewModel。然后,我们要求Active Record在Query数据库中为该类生成相应的表。这是我们发现的最快,最顺畅的方法,可以快速获取为ViewModel类提供服务的Query数据库表。自动生成反映了这样一个现实:表存在的唯一原因是为视图提供服务。
答案 2 :(得分:3)
我们在命令部分使用EF,直接使用ADO.NET =>查询链的DTO。优点:
1)能够优化SQL查询并使用未抽象到ORM层的高级DB存储功能
2)开销减少
但我们只将分离用于要求严格的部分(搜索),其余部分依赖于常见的实体框架模型。
答案 3 :(得分:1)
无需使用其他方法来读取数据库而不是更新数据库。 CQS只是声明更新数据存储的命令应该与从数据存储中读取状态的查询分开。
您仍然可以使用NHibernate从数据存储中读取数据,但您可能希望通过创建两个不同的类来封装数据访问来使其显而易见。一个类具有读取(查询)数据存储的方法,另一个类具有向数据存储发出命令(添加,更新,删除)的方法。
您要避免的是一种从数据库中获取消息的方法,然后将该消息标记为在数据库中读取。这应该是两个不同的方法调用。您不应该更改状态并从同一方法返回值。
答案 4 :(得分:1)
我喜欢将ORM与读取和写入分开,所以我会使用(我使用):
命令的Nhibernate - 精美地映射我的域模型
用于查询的Dapper.net - 精美地映射我的DTO,并且如果查询太复杂,则允许灵活。
他们是完美的一对,就像Han Solo和Chewbacca一样。