MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Champ de désérialisation lorsque le type est modifié à l'aide du pilote MongoDb csharp

Il se passe plusieurs choses. Le principal est que vous devez consommer l'entrée quel que soit le type ou le processus de désérialisation se désynchronise. J'ai testé votre scénario en écrivant un sérialiseur personnalisé appelé ZipCodeSerializer qui gère les nulls et écrit les ZipCodes sous forme de chaînes, mais accepte les chaînes ou les ints en entrée et convertit les ints en chaîne.

J'ai utilisé cette classe pour tester :

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

Et voici le sérialiseur personnalisé que j'ai écrit :

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);
        }
    }
}

Vous devez vous assurer que le sérialiseur personnalisé est connecté, ce que vous pouvez faire comme ceci :

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

Alors maintenant, le champ ZipCode de la classe Address sera géré par le sérialiseur personnalisé.

J'ai créé des données de test à l'aide de BsonDocument pour faciliter le forçage de versions stockées particulières des données dans ma collection de tests :

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));

Voici à quoi ressemblaient les documents en utilisant le shell mongo :

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

nous voyons donc que certains codes postaux sont des chaînes et d'autres des ints (il y a aussi un null ajouté).

Et voici mon code de test :

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

Et le résultat de l'exécution du code de test est :

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

Notez que le code postal qui était un int dans la base de données est maintenant une chaîne.

Le code source complet de mon programme de test est disponible sur :

http://www.pastie.org/3775465