我想知道您如何确保不在EventStore中两次添加同一个人?
让我们说,在您的应用程序上添加了个人数据,但是您要确保在不同的流中不会两次添加相同的个人姓名和生日。
您问您是ReadModels还是在Evenstore中完成?
答案 0 :(得分:1)
我想知道您如何确保不在EventStore中两次添加同一个人?
您要解决的问题的一般形式是set validation。
第1步是严格要求,以确保数据始终唯一-如果数据不必始终唯一,则可以使用检测和纠正方法。参见Pat Helland的Memories, Guesses, and Apologies。粗略地翻译后,您将尽力利用所拥有的信息,如果发现必须还原错误,则进行备份。
如果违反唯一性会使您面临不可接受的风险(例如,由于重复违反了政府规定的隐私要求而被起诉破产),那么您就必须工作。
要验证集合的唯一性,您需要锁定整个集合;在执行中,此锁定可能是悲观的或乐观的。当将整个集合存储在一个位置(也就是说,在一个锁下)时,这相对来说是直截了当的,但是当分布整个集合(又称为多个数据库)时,这是一场噩梦。
如果您的集合是 aggregate (意味着为了更新目的将集合的成员视为一个整体),则DDD的机制很简单。将集合从“存储库”加载到内存中,对集合进行更改,并保留更改。
这种设计适用于事件源,其中每个聚合都具有单个流-您可以通过锁定“该”流来防止种族。
大多数人不希望这种设计,因为集合的成员很大,而且对于大多数数据而言,您只需要这些数据的一小部分,因此将整个集合加载/存储在工作内存中是浪费的。>
因此,他们要做的是将维护唯一性属性的责任从域模型转移到存储。 RDBMS解决方案非常擅长使用。您定义维护该属性的约束,并且数据库确保不允许违反该约束的写操作。
如果您的事件存储是关系数据库,则您可以做同样的事情-事件流和维护集合不变性的表在同一事务中一起更新。
如果事件存储区不是关系数据库?好吧,再次,您必须考虑金钱-如果风险足够高,那么您必须丢弃无法让您用能解决问题的管道解决问题的管道。
在某些情况下,还有另一种方法:将需要唯一的信息编码为流标识符。流将代表“所有名为Bob的用户”,然后您的域模型可以确保Bob流一次最多包含一个活动用户。
然后,您开始考虑Bob的名字是否稳定,以及在不稳定的名称更改时您愿意进行哪些权衡。
人名是一个特别痛苦的问题,因为none of the things we believe about names are true。这样您就可以解决所有常见的唯一性问题,最多可以拨11个。
答案 1 :(得分:1)
如果您要验证这种情况,则应在聚合本身IMO中完成,并且您必须像这样说的那样使用使用读取模型。但是您最终将基础结构代码/依赖关系发送到聚合中/传递到方法中。
在这种情况下,我建议创建一个Person.Id
,Person.Name
,Person.Birthday
的读取模型,然后创建一些使用以下内容的服务,而不是直接创建Person
读取模型表以查找是否存在一行,然后将其汇总回去,或者创建一个新的并将其还回。然后,只要通过此服务完成所有Person-creation,就完全不需要验证。