Storage of composite / nested graph objects

I am currently developing a document repository in Mongo DB that contains a complete breakdown of the material for a specific element. Breakdown is calculated and contains a composite structure.

Domain Model:

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

Now the problem is that the composite structure is incorrectly saved. Reagents remain vague in mongodb.

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

An example of how it should look

 { "_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" : [] } ] } ] } ] } 

What could be the problem?

+3
source share
2 answers

The problem is that you are using a list of abstractions and cannot serialize them to JSON, so basically you will need to write your own serialization. Here is an example of custom serialization that I wrote:

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

In your case, I would write my own Reagent class serialization

+2
source

Doing IBsonSerializer worked :) I made a quick layout and it worked out pretty well: D I got another suggestion from someone who says List<T> will work, we'll try this later this week. And post the results here.

 /* 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" : [] }] }] }] }] } 

Serialization:

 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(); } 
0
source

Source: https://habr.com/ru/post/894480/


All Articles