Cqrs 在事件源中创建大型事件可以吗?

Cqrs 在事件源中创建大型事件可以吗?,cqrs,aggregateroot,event-sourcing,Cqrs,Aggregateroot,Event Sourcing,我们正在使用事件源并从事件流构建聚合。 我有两种骨料——A1和A2。A1用作模板以创建A2。 A1的尺寸可能相当大。 事件源的基本思想是确保在事件对象中捕获对应用程序状态的每个更改。 因此,为了保存A2,我们必须在第一个事件中存储大量信息 这种情况是常见的还是从模板创建不是好主意? 有没有更好的方法来解决这个问题?如果你发布更多关于你的集合和事件的具体例子,会更有帮助。一般来说,如果在您的情况下有意义,您可以创建更细粒度的事件。然后,命令和事件之间没有1-1关系,而是有1-N关系,这完全符合CQ

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

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

如果你发布更多关于你的集合和事件的具体例子,会更有帮助。一般来说,如果在您的情况下有意义,您可以创建更细粒度的事件。然后,命令和事件之间没有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
和在命令处理程序中:

void Handle(CreateInvoce cmd)
{
  var invoice = new Invoice(cmd.InvoiceId, cmd.Customer, cmd.Address, cmd.Lines ....)
  uow.Register(invoice);
}
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);
}
其中仅引发一个InvoceCreated事件

相反,您可以有更细粒度的事件:

InvoiceCreated : Event
- InvoiceId
- Customer
- Address

InvoiceLineAdded
- InvoiceId
- Item
- Vat
- Subtotal
- Etc
然后在命令处理程序中:

void Handle(CreateInvoce cmd)
{
  var invoice = new Invoice(cmd.InvoiceId, cmd.Customer, cmd.Address, cmd.Lines ....)
  uow.Register(invoice);
}
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);
}
在这里,ctor将引发InvoiceCreated事件,AddLine方法将引发InvoiceLineAdded事件。 然后,您可以将InvoiceLineChanged/InvoiceLineRemoved等事件与更新一起使用

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

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

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


希望能有所帮助。

我在这里有一个类似的问题:

通常,一个大类表示您必须检查它的职责,并根据SRP将其划分为更小的类。通过聚合、域事件等。。。您可以遵循相同的方法。通过太多的类,您可以考虑多个有界上下文,等等

问题的另一部分是,命令和事件粒度是一个业务决策。如果你的领域模型认为你的重大事件有意义,那么就使用它。否则,您(或领域专家)应该问问自己,用户的意图是什么,当前事件是否表达了这一意图?仅举一个非常简单的例子,您甚至可以有非常小的域事件:
PhoneNumberChanged
或更小的事件:
PhoneNumberCorrected
PhoneNumberMigrated
(所有这些事件都只包含一个属性,即新的电话号码)。根据这一点,你也可以举办大型活动。Ofc。维护它们要困难得多,过一段时间后,您可能会开始对它们进行版本设置,或者将整个事件存储迁移到另一个域结构下


如果对问题一无所知,很难提供更多帮助。您可能应该告诉我们过去几年中您的大型域事件发生了什么,您以后有问题吗?

一句话,您可以将多个事件创建(作为替代方案)内部化(在聚合中)。