2011-08-18 65 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(); 

}