在 Event Sourcing 中按 属性 聚合重复数据删除

Aggregates deduplication by property in Event Sourcing

我的聚合 Product 具有以下属性:Id、ProductName、ProductPrice 和事件:ProductCreated、ProductNameChanged、ProductPriceChanged 以及命令。

我将我的事件存储在 EventStore 中,并且在执行任何命令之前构建实际的聚合状态,此外,我还具有该聚合的异步读取模型。

如何检查新产品名称,我的数据库中没有其他同名产品(在 CreateProductCommand 或 ChangeProductName 中)?

我无法使用我的读取模型,因为它是异步的,而且我无法读取此聚合类型的所有事件并为每个产品构建实际模型,因为此操作很昂贵。

有几种广泛的方法(请注意,我没有直接的 .Net 或 EventStore 经验,尽管我已经在其他堆栈中开发事件源系统已有几年了):

  • 跟踪哪些产品名称已被声明的读取模型应该不昂贵。因为它是异步更新的,所以在成功创建后的一段时间内,声明的名称不会传播到该读取模型。产品创建和名称更改将是一个传奇,它会检查读取模型,并且仅在检查成功时才传递命令。

  • 解决这个问题的一种方法是采用最终一致性:读取模型能够在两个产品被创建为同名之后进行检测并开始更正过程(例如可以扩充域模型以允许将一个实例标记为另一个实例的替代 ID 并自动融合它们的累积状态;或者,如果这不可能,手动标记和干预通常会起作用。

  • 或者,如果需要更强的一致性,您可以让名称操作传奇保持它看到的名称的状态,而这些名称还没有传播到读取模型。这将为可以操纵名称的速度设置一个上限(因为所有人都必须有效地通过一个过程来协调事情)

请注意,在没有计算机的情况下,必须做出相同的决定:是否会有一个人负责更改目录中的产品名称,或者我们是否允许多人更改名称并接受有发生冲突的可能性(这意味着在发生冲突时决定做什么的一些过程)。 DDD 主要是关于“首先在没有计算机的情况下解决问题”,然后将该解决方案转化为使用计算机的解决方案。

如果允许 ProductName 作为一个聚合 ID,那么让该聚合只是从名称到产品 ID 的映射也是可行的。