在Event Sourcing中创建大型活动是否可以?

Nas*_*ova 6 aggregateroot cqrs event-sourcing

我们正在使用事件采购并从事件流中构建聚合.我有2个聚合 - A1和A2.A1用作模板以创建A2.A1的大小可能相当大.事件源的基本思想是确保在事件对象中捕获对应用程序状态的每个更改.因此,为了节省A2,我们必须在第一个事件中存储大量信息.

这种情况是常见的还是从模板创建并不是一个好主意?有没有更好的方法来解决它?

Yev*_*rov 5

如果您发布更多关于聚合和事件的具体示例,将会有更多帮助。一般来说,如果对您的情况有意义,您可以创建更精细的事件。那么命令和事件之间将不再是 1-1 关系,而是 1-N 关系,这完全符合 CQRS 理论。

给你举个例子:

CreateInvoice : Command
- InvoiceId
- Customer (10 fields)
- Address (5 more fields)
- InvoceLine[] (where each InvoiceLine also have 10 fields or so)
- Rest of 100 or so fields

InvoiceCreated : Event
- InvoiceId
- Customer (10 fields)
- Address (5 more fields)
- InvoceLine[] (where each InvoiceLine also have 10 fields or so)
- Total
- Rest of 100 or so fields
Run Code Online (Sandbox Code Playgroud)

在命令处理程序中:

void Handle(CreateInvoce cmd)
{
  var invoice = new Invoice(cmd.InvoiceId, cmd.Customer, cmd.Address, cmd.Lines ....)
  uow.Register(invoice);
}
Run Code Online (Sandbox Code Playgroud)

其中只会引发一个 InvoceCreated 事件。

相反,您可以拥有更精细的事件:

InvoiceCreated : Event
- InvoiceId
- Customer
- Address

InvoiceLineAdded
- InvoiceId
- Item
- Vat
- Subtotal
- Etc
Run Code Online (Sandbox Code Playgroud)

然后在命令处理程序中:

void Handle(CreateInvoce cmd)
{
  var invoice = new Invoice(cmd.InvoiceId, cmd.Customer, cmd.Address);

  foreach (var line in cmd.Lines)
  {
      invoice.AddLine(line.Item, line.Quantity, line.Price, ...);
  }

  uow.Register(invoice);
}
Run Code Online (Sandbox Code Playgroud)

这里 ctor 将引发 InvoiceCreated 事件,AddLine 方法将引发 InvoiceLineAdded 事件。然后,您可以拥有 InvoiceLineChanged/InvoiceLineRemoved 等事件,您可以将其与更新一起使用。

这将允许您拥有更细粒度的事件,同时仍然允许发出更粗粒度的命令。

当大命令代表来自用户/系统 PoV 的原子操作时,它们就可以了。

PS 关于使用聚合作为模板,我不会为此烦恼,而是会创建数据结构作为累加器来收集中间状态。然后可以简单地对其进行序列化/反序列化。如果填充模板背后没有任何行为 - 那么您根本不需要聚合。它只是一个数据块,稍后将用于创建聚合并运行业务规则。您可能正在使用这个“模板”对象来存储多个请求之间的用户输入状态,例如会话状态,对吧;)?

希望有帮助。