存储复合/嵌套对象图
本文关键字:对象图 嵌套 复合 存储 | 更新日期: 2023-09-27 18:05:52
我目前正在开发一个包含特定项目的完整材料分解的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中保持null
/* 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" : []
}
]
}
]
}
]
}
有什么问题吗?
问题是你正在使用抽象列表,它不能将这些抽象序列化为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();
}
}
在您的例子中,我会在Reagent类级别上编写自定义序列化
实现IBsonSerializer工作:)做了一个快速的模拟,它工作得很好:D我从一个人那里得到了另一个建议,他说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();
}