Reputation: 22223
Say I have the following classes Box and Item. Where a box contains many Items, and an Item can only be in one Box. An Item also knows what Box it is in.
public class Box
{
public virtual int BoxID {get; set:}
public virtual string Name {get; set;}
public virtual IList<Item> Items {get; set;}
}
public class Item
{
public virtual int ItemID {get; set;}
public virtual string Name {get; set;}
public virtual Box ContainerBox {get; set;}
}
The Fluent NHibernate mapping classes might look like this.
public class BoxMap:ClassMap<Box>
{
Id(b=>b.BoxId);
Map(b=>b.Name);
HasMany(b => b.Items)
.Inverse()
.CascadeAll();
}
public class ItemMap:ClassMap<Item>
{
Id(i=>i.ItemId);
Map(i=>i.Name);
References(i => i.ContainerBox );
}
In general this works, but it's not as robust as I would like, as you need to know how associate things correctly. For example the Box.Items.Add()
method will add items to the Box, but not update their ContainerBox
properties. Like wise setting the Item.ContainerBox
property does not add the item to the box.
So I figured I'd make Box.Items and IEnumerable to get rid of the Add() method, and instead add my own AddItem() method that will also set the Item.ContainerBox property.
public class Box
{
private List<Item> _Items = new List<Item>();
public virtual int BoxID {get; set:}
public virtual string Name {get; set;}
public virtual IEnumerable<Item> Items
{
get{return _Items;}
private set
{
_Items.Clear();
_Items.AddRange(value);
}
}
public void AddItem(Item i)
{
if(i.ContainerBox != null) throw new Exception("Item is already in a box!");
i.ContainerBox = this;
_Items.Add(i);
}
}
I'm new to NHibernate, but I'm pretty sure this is a bad idea. Because, when a Box is later persisted from the database Box.Items
wont point at _Items
but rather will be overridden to point at some other NHibernate specific proxy collection. So calling Box.AddItem()
on the persisted box, I think, wont actually add a new Item to the Box.
What is the correct way to do this? I'd like to have a single way to add an Item to a Box which updates Box.Items and Item.ContainerBox regardless of whether the Box is new or persisted from the database.
Upvotes: 1
Views: 109
Reputation: 35117
Change _Items
to protected and set your fluent mapping to the _Items
property and this will work just fine. I've used this technique in a number of ways.
Upvotes: 3