2011-09-21 122 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)時,就其所涉及的情況而言,它仍然與父母相關。我相信這與法拉盛有關,但如果有人能夠清楚地解釋爲什麼這是必要的,請做!