Unknown discriminator value 'MyEvent'

2019-01-27 20:21发布

问题:

Using the MongoDB persistance engine in joliver/EventStore causing the error Unknown discriminator value 'MyEvent'. The issue is only caused when I try to load all events for replaying the events like this.storeEvent.Advanced.GetFrom(new DateTime(2010, 1,1))

The issues is caused in ExtensionsMethods.cs

public class MyClassEvent : IDomainEvent { ... }

public static Commit ToCommit(this BsonDocument doc, IDocumentSerializer serializer)
    {
        if (doc == null)
            return null;

        var id = doc["_id"].AsBsonDocument;
        var streamId = id["StreamId"].AsGuid;
        var commitSequence = id["CommitSequence"].AsInt32;

        var events = doc["Events"].AsBsonArray.Select(e => e.AsBsonDocument["Payload"].IsBsonDocument ? BsonSerializer.Deserialize<EventMessage>(e.AsBsonDocument["Payload"].AsBsonDocument) : serializer.Deserialize<EventMessage>(e.AsBsonDocument["Payload"].AsByteArray)).ToList();
        var streamRevision = doc["Events"].AsBsonArray.Last().AsBsonDocument["StreamRevision"].AsInt32;
        return new Commit(
            streamId,
            streamRevision,
            doc["CommitId"].AsGuid,
            commitSequence,
            doc["CommitStamp"].AsDateTime,
            BsonSerializer.Deserialize<Dictionary<string, object>>(doc["Headers"].AsBsonDocument),
            events);
    }

My configuration is like this:

 Wireup.Init()                
            .UsingMongoPersistence(connectionName, new DocumentObjectSerializer())
            .UsingBsonSerialization()    
            .UsingAsynchronousDispatcher()                                
            .PublishTo(this.container.Resolve<IPublishMessages>())
            .Build();

But have tried almost all kind of serializer options.

回答1:

Try to register your objects (itself the event messages as well as the subjects of the EventStore payloads) using the BsonClassMap.RegisterClassMap method. It seems EventStore's mongo extension handles the string payloads well, but not the deserialized objects ... at least registering the classed was the solution in my case.



回答2:

I just ran into this too. Zsolt's answer was a good starting point, but I ended up solving it slightly different.

Note that I did not only get this when myEventStore.Advanced.GetFrom(...); myEventStore.OpenStream(...) also fails. This makes sense, because both methods use the same IPersistentStream and serializer.

I don't run into this problem when when I first persist an event, before retrieving an event of the same type. Apparently MongoDB creates a ClassMap when it's being asked to serialize a type for the first time.

Anyway, for me the solution was to create a class map for all my event types on application startup. Assuming all type are in the assembly of SimpleCQRS.Event and derive from SimpleCQRS.Event, I do it like this:

var types = Assembly.GetAssembly(typeof(SimpleCQRS.Event))
                    .GetTypes()
                    .Where(type => type.IsSubclassOf(typeof(SimpleCQRS.Event)));
foreach (var t in types)
    BsonClassMap.LookupClassMap(t);

For me this works better than using BsonClassMap.RegisterClassMap<TypeToMap> like Zsolt suggests, because that requires a generic type parameter, meaning you have to manually add each event type.