2010-09-08 198 views
2

我正在與nHibernate合作,試圖理解包集合。我的數據結構是相對直接...添加/刪除項目到包集合

項:

<class name="Entry"> 
<id name="id" column="EntryId"> 
    <generator type="guid.comb"/> 
</id> 
    <property name="Name" column="Name"/> 
<bag name="Results" table="Results" cascade="all"> 
    <key column="EntryId" /> 
    <one-to-many class="Result"/> 
</bag> 
</class> 

結果:

<class name="Result"> 
<id name="id" column="ResultId"> 
    <generator type="guid.comb"/> 
</id> 
<property name="Score" column="Score" /> 
<many-to-one name="Entry" class="Entry" cascade="all" /> 
</class> 

我想這樣做,這似乎並不奏效,是如下:

Entry entry = new Entry(); 
entry.Name = "Name"; 
// have tried saving at this point to: 
// dbSession.SaveOrUpdate(entry); 
Result result = new Result(); 
result.Score = 100; 

entry.Results.Add(result); 
dbSession.SaveOrUpdate(entry); 

它似乎是在數據庫中創建條目記錄,但不是結果記錄。在我的數據庫中,我將EntryId作爲結果表中的外鍵。同樣,我希望能夠從集合中刪除結果對象,並將其保留到數據庫中。我以爲級聯功能,照顧了這一點,但不知道我做錯了......

編輯

現在我將它添加結果對象到數據庫中,但刪除似乎並不工作:

Entry entry = Entry.Load(id); 
entry.Results.Remove(result); 
dbSession.SaveOrUpdate(entry); 

我已經嘗試添加級聯=「所有刪除孤兒」,但這似乎刪除父母和子女。我只想要它從數據庫中刪除一個入口對象?

回答

2

最後,這歸結爲我的HBM文件映射不正確。

Entry.hbm.xml

<bag name="Results" table="Result" lazy="false" inverse="true" cascade="all-delete-orphan"> 
    <key column="EntryId"/> 
    <one-to-many class="Result"/> 
</bag> 

Result.hbm.xml

<many-to-one name="Entry" class="Entry" column="EntryId"/> 

我本來級聯= 「全刪除,孤兒」 在很多一對一的映射,從而是不正確的。發生的是所有的孩子和父母的記錄被刪除。

我現在可以添加和刪除下列要求:

Result r = new Result(); 
Entry entry = new Entry(); 
// AddResult method sets the Entry object of the Result 
// result.Entry = this; 
entry.AddResult(r); 
session.SaveOrUpdate(entry); 

刪除:

entry.Results.Remove(result); 
session.SaveOrUpdate(entry); 
0

要添加到集合中,需要在添加子對象時顯式保存子對象。同樣,從集合中刪除對象時也是如此。

所以,你會怎麼做:

entry.Results.Add(result); 
session.Save(result); 
session.Save(entry); 
session.Flush(); 

外鍵也必須爲空。你必須這樣做的原因是NHibernate必須首先保存孩子,而不與父母關聯。然後,當保存父項時,子項的外鍵列將獲得父項的ID更新,從而創建關係。這是因爲NHibernate可能沒有需要的父ID密鑰值,直到第二個操作(父保存)完成。

我想你已經弄清了這部分。

刪除適用於不同的原因,以同樣的方式 - 從父集合中移除子,然後刪除孩子明確,然後更新父:

entry.Results.Remove(result); 
session.Delete(result); 
session.Update(entry); 
session.Flush(); 

你從集合中刪除結果和更新的紀錄。這隻會告訴Nhibernate刪除條目和結果之間的關係 - 您從未真正刪除過結果對象本身。

+0

我也這麼認爲,但事實並非如此。我提供了答案。 – mickyjtwin 2010-09-15 07:01:47

0

我注意到,你的收藏中,定義了FK列:

<key column="EntryId" /> 

但你是不是在你的many-to-one重寫column,這意味着你有兩個不同的列(進入和ENTRYID)爲同樣的關係。

這可能與否或...但它不傷害檢查:-)

0

如果您正在使用製圖代碼並使用兩種Cascade.All和Cascade.DeleteOrphans選項。與xml映射不同,「按代碼映射」中沒有「all-delete-orphan」的單一選項。

Bag(x => x.Results, c => 
     { 
      c.Key(k => 
      { 
       k.Column("EntryId"); 
      });    
      c.Cascade(Cascade.All | Cascade.DeleteOrphans); 
     }, r => r.OneToMany())