I’m working with nested data (3~4 levels of nesting) and trying to find a way to maintain parent → child and child → parent references without a lot of overhead. My data is Order
info, Order
has a list of Groups
, Group
has a list of Items
, and so on. For simplicity, I’ll focus on Order <-> Item
.
I’ve given Item
an Order
field, which just point to its parent Order
and is populated with data when an Order
is retrieved:
Order RetrieveOrder(string orderId)
{
var order = Orders.Find(Builders<Order>.Filter.Eq(order => order Id, orderId).SingleOrDefault();
foreach (item in order.Items)
item.Order = order;
return order;
}
class Order
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
List<Item> Items { get; set; }
}
class Item
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
[BsonIgnore, JsonIgnore]
public Order Order { get; set; }
}
The way I’m writing updates is by making changes to an item, then calling ReplaceOne()
with the item’s order (and checking ModifiedCount
after the db operation) e.g:
item.ChangeStatus();
var Orders = db.GetCollection<Order>("Orders");
var filter = Builders<Order>.Filter.Eq(order => order.Id, item.Order.Id)
var result = await Orders.ReplaceOneAsync(filter, item.Order)
if (result.ModifiedCount > 0)
//do other stuff
First question, is it possible to set up something like an interceptor which will fill out those parent references when an Order
is retrieved from the db? I’ve explored ClassMaps and custom serializers, but haven’t found a way to get it working yet. Ideally, after an Order
has finished being deserialized, my interceptor/postprocessor would go in and set parent references for Items
(and eventually Groups
and other nested objects). If it’s not possible to do this from the Order
level, can I do in at the Item
level? When I deserialize an Item
, can I set it’s Order
?
This gets me partway, but when an Order
is sent between client/server the Items
lose their parent references (because they’re marked BsonIgnore, JsonIgnore
). I can add string OrderId
to Item
so I can keep those references after de/serialization, but I’m not sure the best approach to get the relevant Order
again at the other end. I can do a “brute force” approach and just do a db query to get my Order
then find the relevant Item
in that order, but that’s a lot of overhead for a pretty frequent operation. Is there a better way? Am I looking in completely the wrong direction?
Short version:
- Can I set up an interceptor/postprocessor which will set
Item.Order
? Can this be done directly from theOrder
or does it have to be per-Item
? - Is there a better way to manage this sort of child → parent reference in my application?
Any help greatly appreciated!