我开始阅读有关CQRS的内容,我感到很困惑。
是否允许在写入端调用读取端以获取其他信息?
http://cqrs.nu/Faq/command-handlers他们说这是不允许的,但在cqrs旅程代码中我发现他们称之为服务' IPricingService'在内部使用DAO服务类。
那么我必须做些什么才能在我的聚合根中获得额外的信息?
答案 0 :(得分:25)
CQRS之旅不应被视为手册。这只是一个团队为CQRS而奋斗的故事,并且只有使用Microsoft堆栈的所有限制。本身,您不应该在命令处理程序或域逻辑中使用您的读取模型。但是,您可以从客户端查询读取模型,以获取命令所需的数据并验证命令。
由于我得到了一些关于这个答案的downvotes,我需要指出,我写的是模式中的既定做法。读取端不访问写入端,写入端也不从读取端获取数据。
然而,"客户"的定义可以成为讨论的主题。例如,我不相信面向公众的JS浏览器应用程序是一个合适的客户端"。相反,我会使用我的REST API层作为"客户端"在CQRS中,Web应用程序只是该客户端的UI层。在这种情况下,REST API服务调用处理将是合法的读取端读取器,因为它需要验证所有UI层发送以防止伪造和验证某些业务规则。完成此工作后,将形成命令并将其发送到写入端。验证和其他所有内容都是同步的,然后命令处理是异步的。
更新:鉴于下面的一些分歧,我想指出Udi's article from 2009一般谈论CQRS,特别是命令和验证。
答案 1 :(得分:2)
CQRS常见问题解答(http://cqrs.nu/Faq)表明:
"如何在有界上下文之间进行通信?
仅限于其公共API。这可能涉及订阅来自另一个有界上下文的事件。或者一个有界的上下文可以像另一个的常规客户端一样发送命令和查询。"
因此,虽然在一个BC内部不可能使用写入侧的读取端,反之亦然,但另一个有界的上下文或服务可以。从本质上讲,这将使用用户界面像人一样。
答案 2 :(得分:1)
是的,前提是您已接受读取端的最终一致性。现在的问题是在哪里。尽管对此没有硬性规定,但最好将数据传递给命令处理程序,而不是在内部检索数据。根据我的观察,有两种方法:
基本上创建一个层,您可以在其中执行必要的查询以构建数据。这与调用 API 一样简单。但是,如果您的微服务在 Lambda/Serverless 上运行,这可能不太合适,因为我们倾向于避免 lambda 调用另一个 lambda 的情况。
让客户端查询数据,然后将其传递给您。为防止篡改,请对其进行加密。您可以在验证 DTO 并将其转换为命令的同一位置实施解密。对我来说,这是一个更好的选择,因为它需要更少的移动部件。
答案 3 :(得分:0)
我认为这取决于。 如果在您的架构中,“命令端”实时(同步)更新投影,您可以调用查询 api。 (虽然这看起来很奇怪)
但是,如果您的预测(查询端)异步更新,那么这样做是个坏主意。有可能获得“不真实”的数据。
也许这种情况表明您应该解决一个设计问题。
例如:如果您认为您需要来自一个上下文/域的信息,则可能是域定义问题。
我是这样认为的,因为在命令操作期间从自身(同一域)读取数据没有多大意义。 (在这种情况下可能是 API 设计问题)