2012-04-12 23 views
8

Muhtemel veri sorunlarından nasıl kurtulacağımı görmek için MongoDb ile birkaç senaryoyu test ediyorum.MongoDb csharp sürücüsü türünü kullanarak tür değiştirilirken serileştirme alanı

Özgün olarak dize olarak atanmış bir zipcode özelliğine sahip sınıflarım var (Adres topluluğuna sahip adresler). Birden çok Adres kaydı kaydettim ve hepsini alabildim. bunu beğendi, var allAddresses = address.FindAllAs();

Posta kodu özelliğini int olarak değiştirdim ve bazı kayıtları kaydettim. Ardından posta kodu özelliğini tekrar dizeye değiştirdim.

Koleksiyonun arkasını okumaya çalıştığımda, beklendiği gibi bir serpme hatası alıyorum. var allAddresses = address.FindAllAs();

Amacım, seri hale getirme işlemini geçersiz kılabilmek, böylece bir alan serileştirme hatası meydana gelirse, onu yok saymayı veya varsayılan bir değer uygulamayı seçebilirim.

Çalışmayan bir özel serileştirici denedim. Herhangi bir öneri takdir edilecektir.

public class MyCustomSerializer : BsonBaseSerializer 
    { 

    public override object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options) 
    { 
     if (bsonReader.CurrentBsonType != BsonType.String) 
     { 
     return string.Empty; 
     } 

     return bsonReader.ReadString(); 
    } 

    public override void Serialize(
       BsonWriter bsonWriter, 
       Type nominalType, 
       object value, 
       IBsonSerializationOptions options) 
    { 
     bsonWriter.WriteStartDocument(); 
     bsonWriter.WriteName("ZipCode"); 
     bsonWriter.WriteString(value.ToString()); 
     bsonWriter.WriteEndDocument(); 
    } 
    } 
+0

, sen cevabı kabul etmelidir:

benim test programının tam kaynak kodu mevcuttur. –

cevap

9

Birkaç şey oluyor. Esas olan, türü ne olursa olsun girişi tüketmeniz veya serileştirme işleminin eşitlenmemesidir. Sen nulls ele ZipCodeSerializer adında özel bir serializer yazma sen senaryoyu test ettik ve ZipCodes dizeleri olarak yazıyor, ama girişte dize veya ints kabul eder ve ints dizeleri dönüştürür.

ben test etmek için bu sınıf kullanılır:

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

Ve bu yazdığım özel seri hale getirici şudur: özel seri hale yapabileceğiniz, hangi bağladım emin olmak zorunda

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

Bunun gibi:

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

Şimdi Adres sınıfının ZipCode alanı custo tarafından ele alınacaktır. m serializer.

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

İşte
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)); 

belgeler Mongo kabuk kullanarak böyle görünüyordu:

Bunun kolay benim test koleksiyonunda verilerin belirli saklanan versiyonlarını zorlamak için yapmak BsonDocument kullanarak test verisi oluşturulur

, bu nedenle bazı ZipCodes dizeleri ve bazıları ints olduğunu görüyoruz (ayrıca atılmış bir boşluk da var).

Ve bu benim test kodu:

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

Ve test kodu çalıştırarak çıktısı: veritabanında bir int oldu zipcode bir dize şimdi olduğu

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

Bildirimi .Bir cevap sorununuzu çözer

http://www.pastie.org/3775465

+1

notunun/sonrasının yanındaki onay, veritabanındaki verileri düzeltmek için daha kolay olabilir, böylece artık ZipCode için karışık türde olmadığından emin olmalısınız! :) –

+0

Teşekkürler, bu çözüm veritabanında milyonlarca kayıt güncelleyemediğim için benim için çalışıyor;) –

İlgili konular