【问题标题】:Aggregates deduplication by property in Event Sourcing在事件溯源中按属性聚合重复数据删除
【发布时间】:2021-08-08 23:10:08
【问题描述】:
我有聚合 Product 属性:Id、ProductName、ProductPrice 和事件:ProductCreated、ProductNameChanged、ProductPriceChanged 和命令。
我将我的事件存储在 EventStore 中,并在执行任何命令之前构建实际的聚合状态,此外我还有此聚合的异步读取模型。
我如何检查新产品名称,我的数据库中没有其他同名产品(在 CreateProductCommand 或 ChangeProductName 中)?
我无法使用我的读取模型,因为它是异步的,并且我无法读取此聚合类型的所有事件并为每个产品构建实际模型,因为此操作很昂贵。
【问题讨论】:
标签:
validation
.net-core
domain-driven-design
event-sourcing
【解决方案1】:
有一些广泛的方法(请注意,我没有直接的 .Net 或 EventStore 经验,尽管我已经在其他堆栈中开发事件源系统几年了):
-
跟踪哪些产品名称已被声明的读取模型不应该很昂贵。因为它是异步更新的,所以在成功创建后的一段时间内,声明的名称不会传播到该读取模型。产品创建和名称更改将是一个检查读取模型并仅在检查成功时传递命令的传奇。
-
解决此问题的一种方法是采用最终一致性:读取模型能够在创建了具有相同名称的两个产品之后检测到并开始一个更正过程(例如,可以增加域模型允许将一个实例标记为另一个实例的备用 ID,并自动融合它们的累积状态;或者,如果这不可能,手动标记和干预通常会起作用)。
-
或者,如果需要更强的一致性,您可以让名称操作传奇维护它所看到的尚未传播到读取模型的名称的状态。这将为名称可以被操纵的速率设置一个上限(因为所有人都必须通过一个流程来协调事情)
请注意,在没有计算机的情况下,必须做出相同的决定:是由一个人负责更改目录中的产品名称,还是允许多人更改名称并接受有机会冲突(这意味着在发生冲突时决定做什么的过程)。 DDD 主要是关于“首先在没有计算机的情况下解决问题”,然后将该解决方案转化为使用计算机的解决方案。
如果允许将 ProductName 用作聚合 ID,那么将聚合只是从名称到产品 ID 的映射也是可行的。