3

在为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",
        // ..

让我感到有点尴尬的是,系统显然可以在不注册所有事件类型的情况下工作,但是选择了一个默认的鉴别器确定策略来防止这种情况。

4

1 回答 1

3

我也遇到过同样的情况。目前,我以与您描述的类似方式执行 BSON 注册。让系统在启动时执行此注册并不困扰我。

此外,我将事件和命令类保存在与实际域逻辑不同的项目中,因为我可以在服务器和客户端项目中“共享”类结构。

于 2012-09-11T16:35:25.300 回答