sql >> Base de Datos >  >> NoSQL >> MongoDB

Deserializar el campo cuando se cambia el tipo usando el controlador MongoDb csharp

Están pasando un par de cosas. La principal es que debe consumir la entrada independientemente del tipo o el proceso de deserialización se desincroniza. Probé su escenario escribiendo un serializador personalizado llamado ZipCodeSerializer que maneja valores nulos y escribe ZipCodes como cadenas, pero acepta cadenas o enteros en la entrada y convierte los enteros en cadenas.

Usé esta clase para probar:

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

Y este es el serializador personalizado que escribí:

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

Debe asegurarse de que el serializador personalizado esté conectado, lo que puede hacer así:

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

Así que ahora el serializador personalizado manejará el campo Código postal de la clase Dirección.

Creé algunos datos de prueba usando BsonDocument para que sea más fácil forzar versiones almacenadas particulares de los datos en mi colección de prueba:

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

Así es como se veían los documentos usando el shell mongo:

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

entonces vemos que algunos ZipCodes son cadenas y algunos son enteros (también hay un valor nulo).

Y este es mi código de prueba:

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

Y el resultado de ejecutar el código de prueba es:

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

Observe que el código postal que era un int en la base de datos ahora es una cadena.

El código fuente completo de mi programa de prueba está disponible en:

http://www.pastie.org/3775465