我们使用域侧的关系数据库和读取端的NoSQL DB构建了基于CQRS的系统 . 域侧遵循经典的关系方法,而读取侧是非规范化的 . 使用命令处理程序发出的事件完成数据复制和转换 .
我有两个关于读取端同步的问题:
- 使用域侧的关系数据完全重建读取模型的最佳方法是什么?
我们假设读模型不同步 . 但即使它始终保持同步,也可能需要导入测试数据库或进行一些批量操作 . 因此,人们可能希望从现有的写模型运行系统,而不需要相应的同步读模型 . 由于我们不使用Event Sourcing,因此无法重播所有事件 .
我目前认为 ReadModelBuilder
基本上在每个表上执行SELECT * FROM并将每个实体转换为读取端表示 . 但这引入了冗余 . ReadModelBuilder需要知道转换是如何完成的 . 事件处理程序也是如此,它通常在命令处理程序执行某些写操作后执行读取端同步 .
我考虑丢弃事件处理程序,并在每个类级别上用同步机制替换它们 . 例如 . 而不是 FooRenamedEventHandler
重命名 foo.name
,它将调用 FooReadModelBuilder
,它重写完整的 Foo
实例 . 但我认为这有弊端 . FooRenamedEventHandler可以更好地处理读取模型中 foo.name
的冗余使用 .
UPDATE: 另一种方法可能是让 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
_
- 您如何检测不同步的读取模型?是否有一般的最佳做法?
先感谢您 .
1 回答
如果您没有保留事件(即不使用
Event sourcing
),则无法轻松重建read-model
. 你的Rebuilder
必须以某种方式尝试对写模型进行反向工程并制作一些奇怪的事件,因为write model
甚至不能包含所有信息,因为它不需要它来完成他的工作 .所以,我的结论是,如果没有
event store
或至少event log
那么你就无法重建你的read-model
. 如果您有这样的事实来源,那么您可以重建它,甚至通过在某些持久性中使用所有已处理事件ID的列表来检测不同步情况 .