我们使用域侧的关系数据库和读取端的NoSQL数据库构建了基于CQRS的系统。域侧遵循经典的关系方法,而读取侧是非规范化的。 使用命令处理程序发出的事件完成数据复制和转换。
我有两个关于读取端同步的问题:
使用域侧的关系数据完全重建读取模型的最佳方法是什么?
假设读取模型不同步。 但即使它始终保持同步,也可能需要导入测试数据库 或做一些批量操作。所以有人可能想要 从现有的写模型运行系统,而没有相应的同步读模型。由于我们不使用事件采购,因此没有 重播所有活动的方式。
我目前认为ReadModelBuilder
基本上是一个
每个表上的SELECT * FROM并将每个实体转换为读取端
表示。但这引入了冗余。
ReadModelBuilder需要知道转换是如何完成的。
通常执行读取端同步的事件处理程序也是如此
在命令处理程序执行一些写操作之后。
我考虑过丢弃事件处理程序并将其替换为
每个级别的同步机制。
例如。而不是FooRenamedEventHandler
重命名foo.name
,它会
拨打FooReadModelBuilder
,重写完整的Foo
实例。
但我认为这有弊端。 FooRenamedEventHandler可以处理很多
在阅读模型中使用foo.name
的冗余用法更好。
更新
另一种方法可以是让ReadModelBuilder
通过将域实例分段为事件来创建读模型实体,这将在顺序执行时构建完整的读取端实体。
例如:
Article
域实体有Name
和Price
。
要构建读取端模型,ReadModelBuilder
可以检查域实体并发出ArticleCreatedEvent
,ArticleRenamedEvent
和ArticlePriceChangedEvent
。这样,转换逻辑将保留在事件处理程序中,但仍可从某种批量复制机制中调用。
例如,ReadModelBuilders可能如下所示:
_
interface IReadModelBuilder<TEntity>
{
//// Returns a sequence of events which replicate the read-model
//// when executed by the event handlers.
Event[] GetReplicationSequence(TEntity instance);
}
END OF UPDATE
_
答案 0 :(得分:1)
如果您没有保留该事件(即不使用Event sourcing
),则无法轻松重建read-model
。你的Rebuilder
必须以某种方式尝试对写模型进行反向工程并制作一些奇怪的事件,因为write model
甚至不能包含所有信息,因为它不需要它来完成他的工作。 / p>
所以,我的结论是,如果没有event store
或至少event log
,那么您就无法重建read-model
。如果您有这样的事实来源,那么您可以重建它,甚至通过在某些持久性中使用所有已处理事件ID的列表来检测不同步情况。