2011-08-18 91 views
3

我目前正在開發Mongo DB中的文檔存儲庫,其中包含特定項目的完整材料細目。計算分解幷包含複合結構。存儲複合/嵌套對象圖

域模型:

public interface IReagent 
{ 
    int ItemId { get; set; } 
    int Quantity { get; set; } 
    ConcurrentBag<IReagent> Reagents { get; set; } 
} 

public class Craft : IReagent 
{ 
    public int ItemId { get; set; } 
    public int Quantity { get; set; } 
    public int SpellId { get; set; } 
    public int Skill { get; set; } 
    public Profession Profession { get; set; } 
    public ConcurrentBag<IReagent> Reagents { get; set; } 
} 

public class Reagent : IReagent 
{ 
    public int ItemId { get; set; } 
    public int Quantity { get; set; } 
    public ConcurrentBag<IReagent> Reagents { get; set; } 
} 

現在的問題是,複合結構沒有被正確存儲。試劑在mongodb中保持爲空。

/* 28 */ 
{ 
    "_id" : ObjectId("4e497efa97e8b617f0d229d4"), 
    "ItemId" : 52186, 
    "Quantity" : 0, 
    "SpellId" : 0, 
    "Skill" : 475, 
    "Profession" : 8, 
    "Reagents" : { } 
}

它應該如何看

{ 
    "_id" : ObjectId("4e497efa97e8b617f0d229d4"), 
    "ItemId" : 52186, 
    "Quantity" : 0, 
    "SpellId" : 0, 
    "Skill" : 475, 
    "Profession" : 8, 
    "Reagents" : [ 
     { 
      "ItemId" : 521833, 
      "Quantity" : 3, 
      "SpellId" : 0, 
      "Skill" : 400, 
      "Profession" : 7, 
      "Reagents" : [ 
       { 
        "ItemId" : 52186, 
        "Quantity" : 3, 
        "SpellId" : 0, 
        "Skill" : 475, 
        "Profession" : 8, 
        "Reagents" : [ 
         { 
          "ItemId" : 52183, 
          "Quantity" : 2, 
          "Reagents" : [] 
         }, 
         { 
          "ItemId" : 521832, 
          "Quantity" : 1, 
          "Reagents" : [] 
         } 
        ] 
       }, 
       { 
        "ItemId" : 52386, 
        "Quantity" : 2 
        "SpellId" : 0, 
        "Skill" : 400, 
        "Profession" : 8, 
        "Reagents" : [ 
         { 
          "ItemId" : 52383, 
          "Quantity" : 2, 
          "Reagents" : [] 
         }, 
         { 
          "ItemId" : 523832, 
          "Quantity" : 1, 
          "Reagents" : [] 
         } 
        ] 
       } 
      ] 
     } 
    ] 
}

這可能是什麼問題實例?

+0

我假設傳入如果是非空?我可以檢查 - 你真的需要'ConcurrentBag '這裏嗎? '列表'不夠嗎?你可能會覺得它更開心嗎?請注意,我也懷疑'IReagant'是否是一個基本問題,除非它存儲了類型信息(即具體的反對類型),它不知道要重建什麼 –

+0

當我在運行時調試時檢查「crafts」時,它包含一個複合結構。我正在使用MS的Parallel .NET 4.0 lib來計算對象圖,因此需要使用ConcurrentBag來避免使用鎖。我已經懷疑過這樣的事情了。它不會支持接口,但Craft也是一個實現的IReagent並被存儲。 –

+0

存儲'Craft'的實例不同於存儲'IReagant'的實例,該實例恰好是* Craft'。特別是對於序列化庫(相信我; p) –

回答

2

問題是你使用的抽象列表,它不能序列化這些到JSON,所以基本上你需要編寫自己的自定義序列化。這裏是例如自定義序列化的我寫道:

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

感謝發佈,毋庸置疑今晚要試試這個:) –

0

Implenting IBsonSerializer工作:)做了一個快速模仿起來,它的工作非常好:DI從別人那得到了另外一個建議,他說List<T>會起作用,本週晚些時候會試用。並在此發佈結果。

/* 3131 */ 
{ 
    "_id" : ObjectId("4e4d58df77d2cf00691aaef2"), 
    "ItemId" : 28432, 
    "Quantity" : 0, 
    "Reagents" : [{ 
     "ItemId" : 23448, 
     "Quantity" : 0, 
     "Reagents" : [{ 
      "ItemId" : 23447, 
      "Quantity" : 0, 
      "Reagents" : [{ 
       "ItemId" : 23427, 
       "Quantity" : 2, 
       "Reagents" : [] 
      }] 
     }, { 
      "ItemId" : 23445, 
      "Quantity" : 0, 
      "Reagents" : [{ 
       "ItemId" : 23424, 
       "Quantity" : 2, 
       "Reagents" : [] 
      }] 
     }] 
    }, { 
     "ItemId" : 23572, 
     "Quantity" : 8, 
     "Reagents" : [] 
    }, { 
     "ItemId" : 28431, 
     "Quantity" : 0, 
     "Reagents" : [{ 
      "ItemId" : 23571, 
      "Quantity" : 0, 
      "Reagents" : [{ 
       "ItemId" : 21885, 
       "Quantity" : 1, 
       "Reagents" : [] 
      }, { 
       "ItemId" : 21884, 
       "Quantity" : 1, 
       "Reagents" : [] 
      }, { 
       "ItemId" : 22451, 
       "Quantity" : 0, 
       "Reagents" : [{ 
        "ItemId" : 21885, 
        "Quantity" : 1, 
        "Reagents" : [] 
       }] 
      }, { 
       "ItemId" : 22452, 
       "Quantity" : 1, 
       "Reagents" : [] 
      }, { 
       "ItemId" : 22457, 
       "Quantity" : 0, 
       "Reagents" : [{ 
        "ItemId" : 21884, 
        "Quantity" : 1, 
        "Reagents" : [] 
       }] 
      }] 
     }, { 
      "ItemId" : 22456, 
      "Quantity" : 0, 
      "Reagents" : [{ 
       "ItemId" : 21885, 
       "Quantity" : 1, 
       "Reagents" : [] 
      }] 
     }, { 
      "ItemId" : 23573, 
      "Quantity" : 0, 
      "Reagents" : [{ 
       "ItemId" : 23446, 
       "Quantity" : 0, 
       "Reagents" : [{ 
        "ItemId" : 23425, 
        "Quantity" : 2, 
        "Reagents" : [] 
       }] 
      }] 
     }, { 
      "ItemId" : 23448, 
      "Quantity" : 0, 
      "Reagents" : [{ 
       "ItemId" : 23447, 
       "Quantity" : 0, 
       "Reagents" : [{ 
        "ItemId" : 23427, 
        "Quantity" : 2, 
        "Reagents" : [] 
       }] 
      }, { 
       "ItemId" : 23445, 
       "Quantity" : 0, 
       "Reagents" : [{ 
        "ItemId" : 23424, 
        "Quantity" : 2, 
        "Reagents" : [] 
       }] 
      }] 
     }] 
    }] 
}

系列化IMPL:

public void Serialize(MongoDB.Bson.IO.BsonWriter bsonWriter, Type nominalType, MongoDB.Bson.Serialization.IBsonSerializationOptions options) 
{ 
    if (nominalType != typeof(IReagent) && nominalType != typeof(Reagent) && nominalType != typeof(Craft)) 
    { 
     throw new ArgumentException("Cannot serialize anything but self"); 
    } 

    bsonWriter.WriteStartDocument(); 

    bsonWriter.WriteInt32("ItemId", this.ItemId); 
    bsonWriter.WriteInt32("Quantity", this.Quantity); 

    if (this.Reagents != null) 
    { 
     bsonWriter.WriteName("Reagents"); 
     bsonWriter.WriteStartArray(); 

     foreach (var r in this.Reagents) 
     { 
      BsonSerializer.Serialize(bsonWriter, r.GetType(), r, options); 
     } 

     bsonWriter.WriteEndArray(); 
    } 

    bsonWriter.WriteEndDocument(); 

}