如何在 NHibernate 中向双向一对多关系添加项目?
假设我有以下类 Box 和 Item。其中一个盒子包含许多项目,并且一个项目只能位于一个盒子中。 Item 也知道它在哪个 Box 中。Fluent
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;}
}
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()
方法会将项目添加到 Box,但不会更新其 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 稍后从数据库中持久化时,Box.Items
不会指向 _Items
,而是会被覆盖以指向其他一些 NHibernate 特定的代理集合。因此,我认为,在持久框上调用 Box.AddItem()
实际上不会向框添加新项目。
这样做的正确方法是什么?我希望有一种方法可以将项目添加到更新 Box.Items 和 Item.ContainerBox 的 Box,无论该 Box 是新的还是从数据库中保留的。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
将
_Items
更改为 protected 并将流畅映射设置为_Items
属性,这样就可以正常工作。我以多种方式使用了这种技术。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.