mongodb-.net-drivercqrsneventstore

Registering of BsonClassMap for each event type required when setting up mongodb persistence for NEventStore?


When setting up mongodb persistence for Oliver's EventStore, is registering of BsonClassMap for each event type required? If I don't do this, I get the exception Unknown discriminator value 'InventoryItemCreated'. I register all event types with MongoDB, like I described here, and then configure my event store:

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();

Is this really necessarily to do?

I ran into this problem while modifying Greg Young's "simplest thing" to support Oliver's event store with MongoDB persistence, code is on github.

Some related observations (tldr)

If I don't register the event types, I can start with an empty event store (because the events don't need to be deserialized). I can add a single inventory item and my event store has a single commit:

/* 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
  }
}

When I restart the application and replay this single event, it can't deserialize PayLoad.Body, because of Unknown discriminator value 'InventoryItemCreated'.

I found two alternative ways to successfully replay the InventoryItemCreated event:

/* 0 */
{
  // ..
  "Events" : [{
      "StreamRevision" : 1,
      "Payload" : {
        "Headers" : { },
        "Body" : {
          "_t" : "SimpleCQRS.InventoryItemCreated, SimpleCQRS",
        // ..

It strikes me as a bit awkward that apparently the systems can work without registering all event types, but picks a default discriminator determining strategy that prevents this.


Solution

  • I've encountered the same situation. For right now, I perform the BSON registration in a similar manner that you've described. It doesn't bother me to have the system perform this registration on startup.

    Also, I keep my events and commands classes in a separate project from the actual domain logic as I can then 'share' the class structures in both the server and client projects.