MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Deserialisieren des Felds, wenn der Typ mit dem MongoDb-csharp-Treiber geändert wird

Es sind ein paar Dinge im Gange. Der wichtigste ist, dass Sie die Eingabe unabhängig vom Typ verbrauchen müssen oder der Deserialisierungsprozess nicht mehr synchron ist. Ich habe Ihr Szenario getestet, indem ich einen benutzerdefinierten Serializer namens ZipCodeSerializer geschrieben habe, der Nullen verarbeitet und ZipCodes als Strings schreibt, aber bei der Eingabe entweder Strings oder Ints akzeptiert und die Ints in Strings umwandelt.

Ich habe diese Klasse zum Testen verwendet:

public class Address
{
    public ObjectId Id;
    public string ZipCode;
}

Und dies ist der benutzerdefinierte Serializer, den ich geschrieben habe:

public class ZipCodeSerializer : BsonBaseSerializer
{
    public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
    {
        var bsonType = bsonReader.CurrentBsonType;
        switch (bsonType)
        {
            case BsonType.Null:
                bsonReader.ReadNull();
                return null;
            case BsonType.String:
                return bsonReader.ReadString();
            case BsonType.Int32:
                return bsonReader.ReadInt32().ToString();
            default:
                var message = string.Format("ZipCodeSerializer expects to find a String or an Int32, not a {0}.", bsonType);
                throw new BsonSerializationException(message);
        }
    }

    public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
    {
        if (value == null)
        {
            bsonWriter.WriteNull();
        }
        else
        {
            bsonWriter.WriteString((string)value);
        }
    }
}

Sie müssen sicherstellen, dass der benutzerdefinierte Serializer angeschlossen ist, was Sie folgendermaßen tun können:

BsonClassMap.RegisterClassMap<Address>(cm =>
    {
        cm.AutoMap();
        cm.GetMemberMap(a => a.ZipCode).SetSerializer(new ZipCodeSerializer());
    });

Das Postleitzahl-Feld der Address-Klasse wird also jetzt vom benutzerdefinierten Serializer behandelt.

Ich habe einige Testdaten mit BsonDocument erstellt, um es einfach zu machen, bestimmte gespeicherte Versionen der Daten in meiner Testsammlung zu erzwingen:

collection.Drop();
collection.Insert(new BsonDocument());
collection.Insert(new BsonDocument("ZipCode", BsonNull.Value));
collection.Insert(new BsonDocument("ZipCode", "12345"));
collection.Insert(new BsonDocument("ZipCode", 56789));

So sahen die Dokumente mit der Mongo-Shell aus:

> db.test.find()
{ "_id" : ObjectId("4f871374e447ad238040e346") }
{ "_id" : ObjectId("4f871374e447ad238040e347"), "ZipCode" : null }
{ "_id" : ObjectId("4f871374e447ad238040e348"), "ZipCode" : "12345" }
{ "_id" : ObjectId("4f871374e447ad238040e349"), "ZipCode" : 56789 }
>

Wir sehen also, dass einige ZipCodes Strings sind und andere Ints (es gibt auch eine Null).

Und das ist mein Testcode:

foreach (var document in collection.FindAll())
{
    Console.WriteLine(document.ToJson());
}

Und die Ausgabe beim Ausführen des Testcodes ist:

{ "_id" : ObjectId("4f871374e447ad238040e346"), "ZipCode" : null }
{ "_id" : ObjectId("4f871374e447ad238040e347"), "ZipCode" : null }
{ "_id" : ObjectId("4f871374e447ad238040e348"), "ZipCode" : "12345" }
{ "_id" : ObjectId("4f871374e447ad238040e349"), "ZipCode" : "56789" }
Press Enter to continue

Beachten Sie, dass die Postleitzahl, die in der Datenbank ein Int war, jetzt eine Zeichenfolge ist.

Der vollständige Quellcode meines Testprogramms ist verfügbar unter:

http://www.pastie.org/3775465