2011-09-16 5 views
8

Utilizzo del motore di persistenza MongoDB in joliver/EventStore provocando l'errore Unknown discriminator value 'MyEvent'. Il problema è causato solo quando provo a caricare tutti gli eventi per riprodurre gli eventi come this.storeEvent.Advanced.GetFrom(new DateTime(2010, 1,1))Valore discriminatore sconosciuto "MyEvent"

I problemi causati nel 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); 
    } 

La mia configurazione è simile a questo:

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

Ma ho provato quasi tutti i tipi di opzioni di serializzazione.

risposta

10

Provare a registrare gli oggetti (a loro volta i messaggi di evento e gli oggetti dei payload EventStore) utilizzando il metodo BsonClassMap.RegisterClassMap. Sembra che l'estensione mongo di EventStore gestisca bene i payload delle stringhe, ma non gli oggetti deserializzati ... almeno la registrazione della classe era la soluzione nel mio caso.

+2

Grazie. Quando ho salvato i commit, il driver mongo db ha registrato le classi stesse, tuttavia in risposta (lettura pura) la mappatura non è stata eseguita. – Jacee

+0

Grazie, anche se non riesco a capire perché questo dovrebbe essere necessario – JacobE

13

Mi sono imbattuto anche in questo. La risposta Zsolt's è stata un buon punto di partenza, ma alla fine ho risolto il problema in modo leggermente diverso.

Nota che non l'ho ricevuto solo quando myEventStore.Advanced.GetFrom(...); myEventStore.OpenStream(...) ha esito negativo. Questo ha senso, perché entrambi i metodi usano lo stesso IPersistentStream e serializzatore.

Non ho riscontrato questo problema quando per la prima volta persisto un evento, prima di recuperare un evento dello stesso tipo. Apparentemente MongoDB crea un ClassMap quando viene chiesto di serializzare un tipo per la prima volta.

In ogni caso, per me la soluzione era creare una mappa di classi per tutti i miei tipi di evento all'avvio dell'applicazione. Supponendo che tutti i tipi sono nel montaggio di SimpleCQRS.Event e derivare da SimpleCQRS.Event, lo faccio in questo modo:

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

Per me questo funziona meglio che usare BsonClassMap.RegisterClassMap<TypeToMap> come Zsolt suggerisce, perché questo richiede un parametro di tipo generico, che significa devi manually add each event type.

+0

+1 ha funzionato anche per me! – RobertMS

+0

Un'eccellente idea di futureproofing, con solo qualche piccola impressione fine/a che tutte le sottoclassi 'SimpleCQRS.Event' saranno aggiunte indiscriminatamente, e che b) che tutte le sottoclassi' Known Type' debbano risiedere nello stesso assembly. – StuartLC