2011-09-21 127 views
0

我成功地在NHibernate中使用一对多的关系,除了一件事。当我从父母的藏品中删除一个孩子记录时,我不希望它删除孩子记录。我只是想让它在子记录中清除外键。保存孤儿,NHibernate的一对多

这是为了让我可以将孩子记录重新附加到不同的父母。

这可能吗?我尝试过各种级联选项,但是当我调用集合上的Remove()时,它们都似乎删除了子级。

这里是我的父映射(一个“SectionItem”)

<class name="Munch.Domain.MenuSection, Munch.Dao" table="menu_section"> 
    <id name="Id" type="Int32"> 
     <generator class="native" /> 
    </id> 
    <property name="Position" /> 
    <property name="Title" /> 
    <property name="Description" /> 
    <bag name="MenuItems" cascade="save-update"> 
     <key column="menuSectionId"/> 
     <one-to-many class="MenuItem"/> 
    </bag>  
    </class> 

儿童对象(“菜单项”)

<class name="Munch.Domain.MenuItem, Munch.Dao" table="menu_item"> 
    <id name="Id" type="Int32"> 
     <generator class="native" /> 
    </id> 
    <property name="Title" /> 
    <property name="Description" /> 
    <property name="Type" /> 
    <property name="Image" /> 
    </class> 

这里是建立了儿童收集并保存测试父母/孩子一气呵成。然后我删除一个孩子(在我做之前记下它的ID),然后尝试检索“已删除”孩子以检查它是否仍在数据库中。我期望它在那里,但是有一个空外键返回给父项。

// Create the menu section 
    MenuSection ms = new MenuSection(); 
    ms.Title = "MenuSectionTitle"; 
    ms.Description = "Description"; 
    ms = menuSectionDao.Save(ms); 

    // Create a couple of menu items 
    MenuItem item1 = new MenuItem(); 
    item1.Title = "AAA"; 
    item1.Description = "AAA Desc"; 

    MenuItem item2 = new MenuItem(); 
    item2.Title = "BBB"; 
    item2.Description = "BBB Desc"; 

    List<MenuItem> items = new List<MenuItem>(); 
    items.Add(item1); 
    items.Add(item2); 

    // Add the items to the menu section 
    ms.MenuItems = items; 

    // Save it and check 
    menuSectionDao.Save(ms); 
    Assert.IsNotNull(ms, "Menu Section wasn't saved"); 
    Assert.True(ms.Id > 0, "Menu Section id is not greater than zero, probably an error"); 

    log.Debug("MenuSection saved with id " + ms.Id); 

    // See what's been saved 
    MenuSection ms2 = menuSectionDao.Find(ms.Id); 
    Assert.IsNotNull(ms2, "Retrieved a null value"); 

    // Check that the menu items were saved too 
    Assert.IsNotNull(ms2.MenuItems); 
    Assert.IsTrue(ms2.MenuItems.Count == 2); 
    Assert.AreEqual(ms2.MenuItems[0].Title, "AAA"); 
    Assert.AreEqual(ms2.MenuItems[1].Title, "BBB"); 

    // Try and remove the item 
    int item1Id = ms2.MenuItems[0].Id; 

    log.Debug("Deleting item 0 with id " + item1Id); 
    ms2.MenuItems.RemoveAt(0); 
    menuSectionDao.Save(ms2); 

    MenuSection ms3 = menuSectionDao.Find(ms.Id); 
    Assert.IsTrue(ms3.MenuItems.Count == 1); 

    // Check we haven't deleted the menu item 
    MenuItem item = menuItemDao.Find(item1Id); 
    Assert.IsNotNull(item); 
} 

感谢(试验在最后一行的方式失败的)那会删除从一个集合中删除实体

+0

你能发布相关的映射吗? – dotjoe

+0

是的,我已将它们添加到最初的帖子。感谢您的看法,感谢它 – Richard

回答

1

唯一的级联的选择是“全删除,孤儿” 。所以它必须是你的代码中删除实体的东西。

另外,请确保在从集合中删除实体时将父引用设置为null。 NHibernate不会为你做这个。

+0

感谢您的提示。为了再次开始工作,我会记住你所说的话并看看我如何继续。 – Richard

+0

对不起,我仍然缺少一些基本的东西。我没有提及孩子的父母,所以我添加了这样的多对一映射: <多对一名称=“MenuSection”... not-null =“false”/ >。 然后我从集合中删除了子项,并将父项引用设置为null: IEnumerator childEnumerator = ms2.MenuItems.GetEnumerator(); childEnumerator.MoveNext(); MenuItem mi =(MenuItem)childEnumerator.Current; mi.MenuSection = null; ms2.MenuItems。除去(MI); menuSectionDao.Save(ms2); 当我找回所有的孩子时,它已经消失了,帮助! – Richard

+0

PS我应该补充一点,我通过自己的DAO检索孩子,以确保 – Richard

0

我真的不明白为什么,但我最终得到了它,所以感谢所有帮助过我的人。

事实证明,我并不需要在孩子中多对一,而且对于我的特殊情况,我并不需要inverse ='true'。我需要做的只是在将其从父母的收藏中删除之前单独保存孩子(使用它自己的DAO)。

IEnumerator childEnumerator = ms2.MenuItems.GetEnumerator(); 
    childEnumerator.MoveNext(); 
    MenuItem mi = (MenuItem)childEnumerator.Current; 

    menuItemDao.Save(mi); // This is the line I needed 

    ms2.MenuItems.Remove(mi); 
    menuSectionDao.Save(ms2); 

当我保存我的孩子(mi)时,就其所涉及的情况而言,它仍然与父母相关。我相信这与法拉盛有关,但如果有人能够清楚地解释为什么这是必要的,请做!