未知的辨别器值 'MyEvent'

8

joliver/EventStore中使用MongoDB持久化引擎会导致错误Unknown discriminator value 'MyEvent'。该问题仅在尝试加载所有事件以重播事件时才会出现,例如this.storeEvent.Advanced.GetFrom(new DateTime(2010, 1,1))

此问题是由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);
    }

我的配置如下:

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

但已经尝试了几乎所有类型的序列化选项。

2个回答

15

我也遇到了这个问题。Zsolt的答案是一个好的起点,但我最终解决了它,稍微有些不同。

请注意,我不仅在myEventStore.Advanced.GetFrom(...)时遇到了这个问题;myEventStore.OpenStream(...)也失败了。这很合理,因为两种方法都使用相同的IPersistentStream和序列化器。

当我首次持久化同一类型的事件之前,我不会遇到这个问题。显然,MongoDB在第一次被要求序列化类型时创建了一个ClassMap

无论如何,对我来说,解决方案是在应用程序启动时为所有我的事件类型创建一个类映射。假设所有类型都在SimpleCQRS.Event的程序集中,并且派生自SimpleCQRS.Event,我像这样做:

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

对我来说,这比像Zsolt建议的使用BsonClassMap.RegisterClassMap<TypeToMap>更好,因为它需要一个通用类型参数,这意味着你必须手动添加每个事件类型

优秀的未来保障想法,只是需要一些小的细节/警告。a)所有“SimpleCQRS.Event”子类会被不加区分地添加进来,b)所有“已知类型”的子类必须驻留在同一个程序集中。 - StuartLC

10

尝试使用BsonClassMap.RegisterClassMap方法注册对象(包括事件消息本身以及EventStore负载的主题)。看起来EventStore的Mongo扩展可以很好地处理字符串载荷,但不是反序列化的对象...至少在我的情况下,注册类是解决方案。


2
谢谢。当我保存了提交时,MongoDB驱动程序自己注册了这些类,但在回复(仅读取)时,映射没有完成。 - Jacee
谢谢,虽然我看不出为什么这是必要的。 - JacobE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接