CQRS - 查询方面

32 nhibernate orm command design-patterns cqrs

许多与CQRS(命令查询可复制性)分离相关的blogsphere文章似乎暗示所有屏幕/视图模型都是平坦的.例如姓名,年龄,出生地等等.因此建议明确我们将它们粘贴到快速阅读源等等.每个视图mySQL等单个表...并用原始的SqlDataReader拉出它们,踢那个令人讨厌的nhibernate ORM等..

然而,虽然我同意域模型不能很好地映射到大多数屏幕,但我使用的许多屏幕都更具有维度,我确信这在LOB应用程序中很常见.

所以我的问题是人们如何处理屏幕,例如它显示客户详细信息的摘要,然后是[更详细]链接等的订单列表....

我想保持查询数据库的直接SQL查询中断外部联接,所以可以构建一个合适的ViewModel来查看,但它似乎有点矫枉过正?

或者(这开始让人感到厌倦)在CustomerSummaryView表中有一个text/big(无论数据库中的类型是什么)列名为Orders,Order summary屏幕网格的列是分隔的,行是|.即使使用XML数据类型,它仍然很脏.

关于最佳实践的任何想法?

Cha*_*ers 33

是的,出现了混乱.下面是它如何发生的:首先,为了真正帮助新人们了解CQRS是一回事,而真正开车回家从典型的分层体系结构的不同之处,人们说这样的话:"你的视图模型可以完全放平",并且"查询数据库中每个视图模型应该有一个表."

但这实际上只是为了推动这一点......不一定每个视图模型必须只有一个表(尽管在大多数情况下你可能应该这样).这些陈述试图说的是:"你必须摆脱一些你已经遵循规范化的规则.使用CQRS架构,你有机会在你的查询频道中建立数据库表根据你的观点的需要而完全塑造其他的东西.确保你充分利用这一点.不要因为这是你习以为常的事情而将这些表归一化.不过,继续做下去曾经被认为是不可想象的事情,例如为每个视图模型制作一个数据库表,或者使视图模型表完全平坦."

还有像你这样的情况,最能满足你需求的模式会有多个表.你甚至可能(上帝保佑)做一两次加入.这很好,只要你真的设计了数据库表来为你的视图服务,反之亦然.但是要小心,很容易在规范化的斜坡上滑动并在Query数据库中的许多视图之间共享数据.不要去那里......根本就没有理由,它会带来更多的成本而不是收益.主要目标是:您的View逻辑应该是死的,简单的死.您希望智能规则存在于房屋的Command端,并且需要在订阅服务器中填充查询通道中的数据.因此,从查询数据库中读取并在屏幕上显示数据的代码应该是简单的(几乎与"被动视图"一样简单).

更新:作为声明的进一步支持,只要您设计了数据库形状以最好地服务于您正在实现的任务,它就不会被"禁止"进行某些连接,请考虑使用OLAP.星型模式是设计用于支持读取的数据库模式的完美示例,它完全适合CQRS的Query端,并且确实涉及连接.连接保持简单,并且它们已到位以进一步增强针对数据库执行的读取任务的目标.


Der*_*ley 5

如果有人真的说你的视图模型应该是扁平的,那么他们要么过于简单化了他们的例子,要么他们正在谈论一堆废话.分层数据也不错,在视图模型中不应该避免.

但是,确实没有"最佳实践".在加载数据方面,这一切都非常主观.您需要找到一个适合您当前团队和系统的解决方案.你还应该了解其他选项是什么,因为你可能会遇到当前解决方案不充分的情况.

以下是我处理此问题的一些方法,具体取决于我正在使用的应用程序,在C#/ .NET中:

  • 数据集和直接ADO.NET,并将数据集直接绑定到屏幕的控件**直接编写SQL代码以加载数据集**使用数据库中的视图加载数据集**使用存储过程加载数据集

  • NHibernate和DTO/Viewmodel对象**我通常在沿着这条路线使用视图时 - 我将在我的域模式之上创建一组视图,将数据反规范化为我需要的模型,然后使用NH加载它通过第二组地图

  • 来自域模型的DTO/Automapper**我不喜欢这种方法,除非我知道我已经从我的域模型加载到内存中的所有东西.我将使用像Automapper这样的工具将数据从我的域模型传输到DTO/ViewModel

我确定还有其他选择,但这些是我经常使用的三种选择,按我使用频率的顺序排列.他们都有自己的成本/收益.但重要的是要理解的是,您可以并且应该以一种使您可以轻松填充屏幕的方式检索数据.