2017-01-26 2 views
1

Ich habe eine Sammlung in meiner Datenbank, wo ich Ereignisse protokollieren. Jeder Ereignistyp hat einen anderen Datensatz. Ich habe dies mit folgender Klasse definiert:C# MongoDb Serialisierung von Dictionary <String, Objekt>

[CollectionName("LogEvent")] 
public class LogEvent 
{ 
    public LogEvent(string eventType) 
    { 
     EventType = eventType; 
     EventData = new Dictionary<string, object>(); 
    } 

    public string EventType { get; private set; } 
    [BsonExtraElements] 
    public IDictionary<string, object> EventData { get; private set; } 
} 

Jetzt - das funktioniert ziemlich gut in gewissem Maße. Solange die Elemente des EventData Wörterbuch sind einfache Typen ...

var event = new LogEvent("JobQueues"){ 
    EventData = new Dictionary<string, object>(){ 
     { "JobId": "job-123" }, 
     { "QueueName": "FastLane" } 
    } 
} 

_mongoCollection.InsertOne(event); 

... ich Mongo Dokumente wie

{ 
    _id: ObjectId(...), 
    EventType: "JobQueued", 
    JobId: "job-123", 
    QueueName: "FastLane" 
} 

Aber sobald ich versuche, einen benutzerdefinierten Typ der hinzufügen Wörterbuch, Dinge funktionieren nicht mehr.

var event = new LogEvent("JobQueues"){ 
    EventData = new Dictionary<string, object>(){ 
     { "JobId": "job-123" }, 
     { "QueueName": "FastLane" }, 
     { "JobParams" : new[]{"param-1", "param-2"}}, 
     { "User" : new User(){ Name = "username", Age = 10} } 
    } 
} 

Das gibt mir Fehler wie ".NET type ... cannot be mapped to BsonType."

Wenn ich den [BsonExtraElements] Tag zu entfernen, und [BsonDictionaryOptions(DictionaryRepresentation.Document)] Es wird serialize Sachen ohne Fehler starten, aber es gibt mir ein ganz anderes Dokument, das Ich mag es nicht. .

{ 
    _id: ObjectId(...), 
    EventType: "JobQueued", 
    EventData: {  
     JobId: "job-123", 
     QueueName: "FastLane", 
     User: { 
     _t: "User", 
     Name: "username", 
     Age: 10 
     }, 
     JobParams : { 
     _t: "System.String[]", 
     _v: ["param-1", "param-2"] 
     } 
    } 
} 

Was ich will, ist das folgende Ergebnis:

{ 
    _id: ObjectId(...), 
    EventType: "JobQueued", 
    JobId: "job-123", 
    QueueName: "FastLane", 
    User: { 
    Name: "username", 
    Age: 10 
    }, 
    JobParams : ["param-1", "param-2"] 
} 

Weiß jemand, wie man das erreicht?

(Ich verwende den C# mongodriver v2.3)

Antwort

0

So funktioniert MongoDriver, weil es Informationen von der Art muss es zurück deserilize. Was Sie tun können, ist zu Ihrer eigenen CustomMapper für Benutzerklasse zu schreiben und registrieren:

public class CustomUserMapper : ICustomBsonTypeMapper 
{ 
    public bool TryMapToBsonValue(object value, out BsonValue bsonValue) 
    { 
     bsonValue = ((User)value).ToBsonDocument(); 
     return true; 
    } 
} 

Irgendwo auf Startprogramm:

BsonTypeMapper.RegisterCustomTypeMapper(typeof(User), new CustomUserMapper()); 

das funktionieren wird, und ich haben es geschafft, Ihre Daten genau serialisiert wie du willst.

Aber: Wie Sie es wollen zurück deserialisieren, wil Sie Ihre User Klasse als Dictionary bekommen, weil Fahrer keine Informationen über haben hiow es deserialisieren:

enter image description here

+0

Deserialisierung ist kein Problem . Dies ist eine "nur Anhängen" -Sammlung, und in dem seltenen Zustand, in dem etwas zurückgelesen wird, wird es durch benutzerdefinierte Projektionen geschehen. Anyway - benutzerdefinierte Serialisierer ist keine gute Option, da ein Punkt davon ist in der Lage, "was auch immer" zum Protokoll hinzuzufügen. – Vegar

+0

Ich hatte eine Art Workaround, indem ich die Daten zuerst als json mit json.net serialisierte und dann mongo bat, ein bsondocument des json zu erstellen. Es hat irgendwie funktioniert, aber keine optimale Lösung ... – Vegar

+0

@Vegar Vielleicht ist Ihr Workaround die beste Lösung. MongoDrive könnte alles, was zur Sammlung gehört, hinzufügen, aber es sollte sicher sein, dass es möglich ist, es genau in der Sam-Form zurückzubekommen, und dafür werden Typedeskriptoren verwendet. –

Verwandte Themen