在为Oliver 的 EventStore设置 mongodb 持久性时,是否BsonClassMap
需要为每种事件类型注册?如果我不这样做,我会得到异常Unknown discriminator value 'InventoryItemCreated'
。我向 MongoDB 注册了所有事件类型,就像我在这里描述的那样,然后配置我的事件存储:
var types = Assembly.GetAssembly(typeof(SimpleCQRS.Event))
.GetTypes()
.Where(type => type.IsSubclassOf(typeof(SimpleCQRS.Event)));
foreach (var t in types)
BsonClassMap.LookupClassMap(t);
var store = Wireup.Init()
.UsingMongoPersistence("mongo", new DocumentObjectSerializer())
.UsingSynchronousDispatchScheduler()
.DispatchTo(new DelegateMessageDispatcher(DispatchCommit))
.Build();
这真的有必要吗?
我在修改 Greg Young 的“最简单的事情”以支持具有 MongoDB 持久性的 Oliver 的事件存储时遇到了这个问题,代码在 github 上。
一些相关的观察 (tldr)
如果我不注册事件类型,我可以从一个空的事件存储开始(因为事件不需要反序列化)。我可以添加一个库存项目,我的事件存储有一个提交:
/* 0 */
{
"CommitId" : new BinData(3, "4iXrzvzNYEyKmGweCKkOVQ=="),
"CommitStamp" : ISODate("2012-08-01T08:08:35.795Z"),
"Dispatched" : true,
"Events" : [{
"StreamRevision" : 1,
"Payload" : {
"Headers" : { },
"Body" : {
"_t" : "InventoryItemCreated",
"Version" : 0,
"_id" : new BinData(3, "36qvklv+xU2+mDhVUlzmBg=="),
"Name" : "abc"
}
}
}],
"Headers" : { },
"_id" : {
"StreamId" : new BinData(3, "36qvklv+xU2+mDhVUlzmBg=="),
"CommitSequence" : 1
}
}
当我重新启动应用程序并重播此单个事件时,它无法反序列PayLoad.Body
化,因为Unknown discriminator value 'InventoryItemCreated'
.
我找到了两种成功重播InventoryItemCreated
事件的替代方法:
- 当我在重播之前创建另一个库存项目时,我可以重播所有事件;显然 MongoDB 然后知道鉴别器。
- 手动将鉴别器更改为完整的类型名称:
/* 0 */
{
// ..
"Events" : [{
"StreamRevision" : 1,
"Payload" : {
"Headers" : { },
"Body" : {
"_t" : "SimpleCQRS.InventoryItemCreated, SimpleCQRS",
// ..
让我感到有点尴尬的是,系统显然可以在不注册所有事件类型的情况下工作,但是选择了一个默认的鉴别器确定策略来防止这种情况。