MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Deserializacja pola po zmianie typu za pomocą sterownika MongoDb csharp

Dzieje się kilka rzeczy. Głównym z nich jest to, że musisz zużywać dane wejściowe niezależnie od typu lub proces deserializacji nie jest zsynchronizowany. Przetestowałem Twój scenariusz, pisząc niestandardowy serializator o nazwie ZipCodeSerializer, który obsługuje wartości null i zapisuje kody pocztowe jako ciągi, ale akceptuje ciąg znaków lub dane liczbowe na wejściu i konwertuje dane liczbowe na ciąg.

Użyłem tej klasy do testowania:

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

A to jest niestandardowy serializator, który napisałem:

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

Musisz upewnić się, że niestandardowy serializator jest podłączony, co możesz zrobić w ten sposób:

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

Więc teraz pole ZipCode klasy Address będzie obsługiwane przez niestandardowy serializator.

Utworzyłem kilka danych testowych za pomocą BsonDocument, aby ułatwić wymuszenie określonych przechowywanych wersji danych w mojej kolekcji testów:

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

Oto jak dokumenty wyglądały przy użyciu powłoki mongo:

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

więc widzimy, że niektóre kody pocztowe są ciągami, a inne intami (jest też wrzucony null).

A to jest mój kod testowy:

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

Wynikiem uruchomienia kodu testowego jest:

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

Zauważ, że kod pocztowy, który był int w bazie danych, jest teraz ciągiem.

Pełny kod źródłowy mojego programu testowego jest dostępny pod adresem:

http://www.pastie.org/3775465




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB wysyła zapytania do wielu kolekcji jednocześnie

  2. Wiele warunków granicznych w mongodb

  3. Połączenie Go i MongoDB nie będzie działać z dziennikiem paniki, brak dostępnego serwera

  4. MongoDB $mod

  5. grupuj według dnia/miesiąca i weź średnią ocen z tego dnia/miesiąca w mongo