保留孤儿,NHibernate一对多

时间:2011-09-21 13:24:22

标签: 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>

子对象('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);
}

(顺便说一下,测试在最后一行失败了)

由于

2 个答案:

答案 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)时,就其而言,它仍然与父母有关。我确定它与法拉盛有关,但如果有人能够清楚地解释为什么这是必要的,请做!