2011-09-16 30 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