除了一件事,我在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>
子对象('MenuItem')
<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 :(得分:1)
删除从集合中删除的实体的唯一级联选项是“all-delete-orphan”。因此,必须在代码中删除实体。
此外,确保在从集合中删除实体时将父引用设置为null。 NHibernate不会为你做这件事。
答案 1 :(得分: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)时,就其而言,它仍然与父母有关。我确定它与法拉盛有关,但如果有人能够清楚地解释为什么这是必要的,请做!