MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Campo di deserializzazione quando il tipo viene modificato utilizzando il driver csharp MongoDb

Ci sono un paio di cose in corso. Il principale è che devi consumare l'input indipendentemente dal tipo o il processo di deserializzazione non è sincronizzato. Ho testato il tuo scenario scrivendo un serializzatore personalizzato chiamato ZipCodeSerializer che gestisce i valori null e scrive i codici zip come stringhe, ma accetta string o ints in input e converte gli ints in string.

Ho usato questa classe per testare:

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

E questo è il serializzatore personalizzato che ho scritto:

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

Devi assicurarti che il serializzatore personalizzato sia collegato, cosa che puoi fare in questo modo:

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

Quindi ora il campo ZipCode della classe Address sarà gestito dal serializzatore personalizzato.

Ho creato alcuni dati di test utilizzando BsonDocument per semplificare la forzatura di particolari versioni memorizzate dei dati nella mia raccolta di test:

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

Ecco come apparivano i documenti usando la mongo shell:

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

quindi vediamo che alcuni ZipCode sono stringhe e altri sono int (c'è anche un null lanciato).

E questo è il mio codice di prova:

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

E l'output dell'esecuzione del codice di test è:

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

Nota che il codice postale che era un int nel database ora è una stringa.

Il codice sorgente completo del mio programma di test è disponibile all'indirizzo:

http://www.pastie.org/3775465