2011-09-17 3 views
3

現在、Simple.DataとMongoDbアダプタを使用しています。私たちは、ドキュメントを検索したら、私たちは、例えば、POCOにそれをキャストしていない:Simple.DataでMongoDbコレクションのデータ構造を変更する方法を教えてください。

(User)db.Users.FindById(1234); 

は、まず、これは非常にうまく機能(一体ええ、何のスキーマを!)。ただし、Userオブジェクトの構造を変更したり(たとえば、新しいフィールドを追加したり、フィールドのデータタイプを変更するなど)、新しいクラス構造と一致しないため、元のドキュメントをキャストできなくなります。これを解決するには

は、我々はこれまでに二つの最も率直なアプローチを試してみた:

  1. マニュアルデータの更新を文書構造の変化を反映します。現在のところOkですが、プロジェクトが複数の環境にまたがって展開されている場合は管理できません/生産に移す
  2. 手動マッピング。例えば。 SimpleRecordを辞書にキャスティングし、メンバを手動で評価します。私はこのアプローチのパフォーマンスについて懸念していますが、まだベンチマークしていません。私はまた、宛先タイプのリフレクションを使用してメンバー名を特定しないで汎用的にする方法を見つけていないことに懸念しています。

これは、RubyPythonで解決されました。前者はより多くをアピールします(Mingの古いスキーマバージョンの維持管理は過度なことかもしれません)。

私は逃げ出して何か狂ったようにする前に、Simple.Dataでこの問題を解決した人は誰ですか?スキーマレスデータベースの文書構造の変更を処理するためのベストプラクティスに関する指針を誰でも提供できますか?

+0

非常に多くのことがコンストラクタのシナリオに依存しますが、mongoでは「これはどうやってやったのですか」という方法はありませんので、いくつかのユースケースは便利です。 –

+1

@Hohhiほとんどの場合、フィールドの追加やデータ型の変更が行われています。文書 'public List Activities'に新しいフィールドを追加するか、タイプを変更します。' public int SomeValue'は 'public string SomeValue'になります。現時点で開発者は2人しかいないので、これを管理するのは大丈夫でしたが、開発者が増え、ビルドが増えると、頭痛を引き起こすようです。私が見る限り、古いデータを変更したり、データの変更を無視するようにマッピングしたりするケースがありますが、これを比較的シームレスにする方法についてはあまり明確ではありません。急速な変化... –

答えて

2

カスタムシリアル化を調べます。私の場合は速くて便利でした。

public class FieldsWrapper : IBsonSerializable 
{ 
    public List<DataFieldValue> DataFieldValues { get; set; } 


    public object Deserialize(MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options) 
    { 
    if (nominalType != typeof(FieldsWrapper)) throw new ArgumentException("Cannot deserialize anything but self"); 
    var doc = BsonDocument.ReadFrom(bsonReader); 
    var list = new List<DataFieldValue>(); 
    foreach (var name in doc.Names) 
    { 
     var val = doc[name]; 
     if (val.IsString) 
      list.Add(new DataFieldValue {LocalIdentifier = name, Values = new List<string> {val.AsString}}); 
     else if (val.IsBsonArray) 
     { 
      DataFieldValue df = new DataFieldValue {LocalIdentifier = name}; 
      foreach (var elem in val.AsBsonArray) 
      { 
       df.Values.Add(elem.AsString); 
      } 
      list.Add(df); 
     } 
    } 
    return new FieldsWrapper {DataFieldValues = list}; 
    } 


    public void Serialize(MongoDB.Bson.IO.BsonWriter bsonWriter, Type nominalType, IBsonSerializationOptions options) 
    { 
     if (nominalType != typeof (FieldsWrapper)) 
      throw new ArgumentException("Cannot serialize anything but self"); 
     bsonWriter.WriteStartDocument(); 
     foreach (var dataFieldValue in DataFieldValues) 
     { 

      bsonWriter.WriteName(dataFieldValue.LocalIdentifier); 
      if (dataFieldValue.Values.Count != 1) 
      { 
       var list = new string[dataFieldValue.Values.Count]; 
       for (int i = 0; i < dataFieldValue.Values.Count; i++) 
        list[i] = dataFieldValue.Values[i]; 
       BsonSerializer.Serialize(bsonWriter, list); 
      } 
      else 
      { 
       BsonSerializer.Serialize(bsonWriter, dataFieldValue.Values[0]); 
      } 
     } 
     bsonWriter.WriteEndDocument(); 
    } 

} 

これは他の方法がありますが、あなたのケースでは最も適用性が高いと思われます。私たちはプロダクションで辞書をテストしましたが、他のすべてのものと同じくらい速いです。辞書があなたのドメインにとって自然でない場合にはマッピングに時間が掛からず、カスタムの直列化に行きます。

+0

ありがとう@Hohhi、私たちはこれを試しているし、これまでのところとても良い。 –

関連する問題