sql >> Databáze >  >> NoSQL >> MongoDB

Deserializace pole při změně typu pomocí ovladače MongoDb csharp

Děje se pár věcí. Hlavním z nich je, že musíte spotřebovat vstup bez ohledu na typ, jinak se proces deserializace nesynchronizuje. Testoval jsem váš scénář psaním vlastního serializátoru s názvem ZipCodeSerializer, který zpracovává hodnoty null a zapisuje PSČ jako řetězce, ale na vstupu přijímá buď řetězec nebo ints a převádí ints na řetězec.

Tuto třídu jsem použil k testování:

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

A toto je vlastní serializátor, který jsem napsal:

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

Musíte se ujistit, že je vlastní serializátor připojen, což můžete udělat takto:

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

Nyní tedy pole ZipCode třídy Address bude zpracovávat vlastní serializátor.

Vytvořil jsem některá testovací data pomocí BsonDocument, aby bylo snadné vynutit konkrétní uložené verze dat v mé testovací kolekci:

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

Takto vypadaly dokumenty pomocí mongo shellu:

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

takže vidíme, že některá PSČ jsou řetězce a některá jsou ints (je tam také vhozena nula).

A toto je můj testovací kód:

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

A výstup spuštění testovacího kódu je:

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

Všimněte si, že PSČ, které bylo v databázi int, je nyní řetězec.

Úplný zdrojový kód mého testovacího programu je k dispozici na adrese:

http://www.pastie.org/3775465




  1. Jak porovnat agregované ($graphLookup) prvky v MongoDB?

  2. Převod dotazu Mongo na Laravel, vnořený elemMatch

  3. Aggregate Query v Mongodb vrací konkrétní pole

  4. aktualizovat konkrétní prvek z pole vnořených dokumentů mongodb, kde má dvě shody