2011-09-16 32 views
8

使用MongoDB持久引擎joliver/EventStore导致错误Unknown discriminator value 'MyEvent'。此问题已不仅造成当我尝试加载所有事件重播事件,如this.storeEvent.Advanced.GetFrom(new DateTime(2010, 1,1))未知鉴别值'MyEvent'

的问题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(); 

但已尝试几乎所有种类的串行器选项。

回答

10

尝试使用BsonClassMap.RegisterClassMap方法注册对象(本身是事件消息以及EventStore有效内容的主题)。看来EventStore的mongo扩展很好地处理了字符串有效载荷,但不是反序列化的对象......至少注册分类是我的案例中的解决方案。

+2

谢谢。当我保存提交时,mongo db驱动程序自己注册了这些类,但是在回复(纯粹阅读)时映射没有完成。 – Jacee

+0

谢谢,虽然我不明白为什么这应该是必要的 – JacobE

13

我也碰到过。 Zsolt's答案是一个很好的起点,但我最终解决了这个问题。

请注意,我并不只在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); 

对于我这个作品比使用BsonClassMap.RegisterClassMap<TypeToMap>像Zsolt的建议更好,因为这需要一个泛型类型参数,这意味着你必须manually add each event type

+0

+1为我工作! – RobertMS

+0

出色的futureproofing理念,只需要一些小的细小打印/注意a)所有'SimpleCQRS.Event'子类将被不加区分地添加,并且b)所有'已知类型'子类必须驻留在同一个程序集中。 – StuartLC