假设我有以下课程框和项目。如果一个箱子包含很多物品,并且一个物品只能在一个箱子中。一个项目也知道它是什么盒子。如何添加项目到NHibernate中的双向一对多关系?
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;}
}
Fluent NHibernate映射类可能看起来像这样。
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);
}
一般情况下,这个方法可行,但它不像我想的那样健壮,因为您需要知道如何正确地关联事物。例如,Box.Items.Add()
方法将项目添加到禁区,但是没有更新自己的ContainerBox
性能。如明智设置Item.ContainerBox
属性不会将项目添加到框中。
所以我想我会让Box.Items和IEnumerable摆脱Add()方法,而是添加我自己的AddItem()方法,该方法也将设置Item.ContainerBox属性。
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);
}
}
我是NHibernate的新手,但我敢肯定这是一个坏主意。因为,当一个框稍后从数据库Box.Items
不会坚持点在_Items
而是将覆盖在其他一些NHibernate的特定的代理收集点。因此,我认为,在持久化框上调用Box.AddItem()
,实际上不会将新项目添加到框中。
什么是做这种正确的方法是什么?我希望有一种方法可以将一个Item添加到Box中,该Box可以更新Box.Items和Item.ContainerBox,而不管Box是新的还是从数据库持久化的。
什么是流利的映射是什么样子?我没有看到你如何将受保护的成员放在lambda表达式中。 – dotjoe 2011-04-21 01:21:27
以下是我所做的似乎工作:HasMany(b => b.Items).Access.CamelCaseField(Prefix.Underscore) – 2011-04-21 02:48:52
也看到此页http://wiki.fluentnhibernate.org/Mapping_a_collection_that_uses_a_private_backing_field和此页面http:///wiki.fluentnhibernate.org/Fluent_mapping_private_properties – 2011-04-21 02:49:50