如何在 NHibernate 中向双向一对多关系添加项目?

发布于 2024-11-02 07:56:50 字数 1931 浏览 1 评论 0原文

假设我有以下类 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

只是我以为 2024-11-09 07:56:50

_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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文