CQRS事件不包含更新读取模型所需的详细信息 [英] CQRS events do not contain details needed for updating read model

查看:111
本文介绍了CQRS事件不包含更新读取模型所需的详细信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不了解CQRS的一件事:当引发的事件不包含更新读取模型所需的详细信息时,如何更新读取模型。

There is one thing about CQRS I do not get: How to update the read model when the raised event does not contain the details needed for updating the read model.

不幸的是,这是一个很常见的情况。

Unfortunately, this is a quite common scenario.

示例:我将用户添加到组中,因此发送了addUserToGroup(userId,groupId)命令。接收到的信息,由命令处理程序处理,创建,存储和发布userAddedToGroup事件。

Example: I add a user to a group, so I send a addUserToGroup(userId, groupId) command. This is received, handled by the command handler, the userAddedToGroup event is created, stored and published.

现在,事件处理程序将接收此事件以及两个ID。现在将出现一个视图,其中列出了所有用户及其所在组的名称。要更新该视图的读取模型,我们确实需要用户ID(拥有)和组名(我们不需要)

Now, an event handler receives this event and the both IDs. Now there shall be a view that lists all users with the names of the groups they're in. To update the read model for that view, we do need the user id (which we have) and the group name (which we don't have, we only have its id).

所以问题是:如何处理这种情况?

So the question is: How do I handle this scenario?

目前,我想到了四个选择,每个选择都有其特定的缺点:

Currently, four options come to my mind, all with their specific disadvantages:


  1. 读取模型询问域。 =>禁止,甚至不可能,因为域仅具有行为,没有(公共)状态。

  1. The read model asks the domain. => Forbidden, and not even possible, as the domain only has behavior, no (public) state.

读取模型从另一个表读取组名在读取模型中。 =>可以,但是如果没有匹配的表怎么办?

The read model reads the group name from another table in the read model. => Works, but what if there is no matching table?

向事件添加必要的数据。 =>不起作用,因为这意味着我也必须更新所有以前的事件,并且无法预见一天可能需要哪些数据。

Add the neccessary data to the event. => Does not work, as this means that I had to update all previous events as well, and I cannot foresee which data I may need one day.

不要通过常规事件处理程序来处理事件,而是在后台启动ETL流程来处理事件存储,创建必要的数据并编写读取模型。 =>可以,但是对我来说,对于这种简单的情况,这似乎有点过多的开销。

Do not handle the event via a "usual" event handler, but start an ETL process in the background that deals with the event store, creates the neccessary data and writes the read model. => Works, but to me this seems a little bit of way too much overhead for such a simple scenario.

因此,问题是:如何正确处理这种情况?

So, the question is: How do I deal with this scenario correctly?

推荐答案

事件不一定代表一对一-最初启动进程的命令的一个映射。例如,如果您有命令:

Events don't necessarily represent a one-to-one mapping of the commands that have initiated the process in the first place. For instance, if you have a command:

SubmitPurchaseOrder
    Shopping Cart Id
    Shipping Address
    Billing Address

所产生的事件可能类似于以下内容:

The resulting event might look like the following:

PurchaseOrderSubmitted
    Items (Id, Name, Amount, Price)
    Shipping Address
    Shipping Provider
    Our Shipping Cost
    Shipping Cost billed to Customer
    Billing Address
    VAT %
    VAT Amount
    First Time Customer
    ...

通常,信息可用于域模型(通过命令提供或作为已知聚合的内部状态或通过计算得到)

Usually the information is available to the domain model (either by being provided by the command or as being known internal state of the concerned aggregate or by being calculated as part of processing.)

此外,在查询过程中,可以通过查询读取模型甚至不同的BC来丰富事件(例如,根据状态检索实际的增值税百分比)处理。

Additionally the event can be enriched by querying the read model or even a different BC (e.g. to retrieve the actual VAT % depending on state) during processing.

Y您正确地假设事件可以(并且可能会)随时间变化。如果您使用版本控制,则基本上根本没有关系:添加新事件(例如 SubmitPurchaseOrderV2 ),并将适当的事件处理程序添加到所有应该使用它的类中。无需更改旧事件,因为您无需修改​​界面,而是对其进行扩展,因此仍然可以使用。这基本上可以归结为实践中的开放/关闭原则的一个很好的例子。

You're correctly assuming that events can (and probably will) change over time. This basically doesn't matter at all if you employ versioning: Add the new event (e.g. SubmitPurchaseOrderV2) and add an appropriate event handler to all the classes that are supposed to consume it. No need to change the old event, it can still be consumed since you don't modify the interface, you extend it. This basically comes down to a very good example of the Open/Closed Principle in practice.

这篇关于CQRS事件不包含更新读取模型所需的详细信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆