据我了解,CQRS 提倡将读取模型与域模型分开,并为每个必要的域模型投影使用特定的读取模型。
从使用角度来看,读取模型的存储和检索方式应该是透明的——您发出查询并获取读取模型,而不关心它是如何制作的。
许多示例和文章使用单独的表来存储读取模型并通过响应域模型更改来重新生成它们。
我不太喜欢这种方法,原因如下:
- 并非经常需要所有可能的读取模型;
- 需求更改可能会使现有的读取模型无效,因此需要重新生成所有读取模型;
- 如果由于某种原因读取模型包含无法在生成时存储但需要计算的属性,您将被迫使用存储过程/函数/视图;
- 由于在域模型更改时使用应用程序级缓存的情况下,读取模型与域模型是分开的,因此您需要通知所有应用程序旧的读取模型需要从缓存中逐出;
- 有时不可能也不希望完全非规范化复杂对象图,因此您需要读取与特定域实体版本一致的模型,即它们需要在同一事务中生成;
- 一些域实体具有经常更改但需要包含在每个读取模型中的属性。
基于此,我正在考虑让查询服务应该:
- 对于需要频繁生成的读取模型和/或域实体的简单投影:不要存储它们,而是通过查询数据库中的域模型实体通过 ORM 生成它们;
- 对于不需要频繁生成且复杂的域实体投影的读取模型,生成它们并存储在数据库表中。
我还看到有些人建议将读取模型存储为 blob。将读取模型存储为 blob 的问题在于,如果您需要在它们上进行搜索,则需要提取属性以进行索引;如果您需要全文搜索,即使您必须以全文可以理解的格式存储它们工具。
如您所见,我基本上希望读取仅在查询执行后存在的模型,而不是基于域更改事件生成的模型。CQRS 可以接受这个解决方案吗?我研究 CQRS 的原因是通过将可缓存的视图模型与用户操作处理分离来改进应用程序架构,让 AJAX 启用的 Web 应用程序在用户操作后进行异步更新,并通过将业务逻辑全部放置来减少初级开发人员生成不可维护代码的空间在我看来,CQRS 的地方甚至不忠实的实施似乎是朝着正确方向迈出的良好一步。