2009-11-27 50 views
0

我有兩個相關的對象:ProgramSession和ProgramTask,具有一對多的關係。一個ProgramSession有許多ProgramTasks。所以物體看起來是這樣的:NHibernate:父列表屬性和相關的子屬性不同步

public class ProgramSession 
{ 
    public virtual IList<ProgramTask> ProgramTasks 
    { 
     get { return _programTasks; } 
     set { _programTasks = value; } 
    } 
} 

public class ProgramTask 
{ 
    public virtual ProgramSession ProgramSession 
    { 
     get { return _programSession; } 
     set { _programSession = value; } 
    } 
} 

而且映射...

ProgramSession.hbm.xml

<bag name="ProgramTasks" lazy="false" cascade="all-delete-orphan" inverse="true" > 
    <key column="SessionUid"></key> 
    <one-to-many class="ProgramTask"></one-to-many> 
</bag> 

ProgramTask.hbm.xml

<many-to-one name="ProgramSession" column="SessionUid" class="ProgramSession" /> 

的問題當我嘗試更改ProgramTask的ProgramSession時開始。

如果我從舊會話的ProgramSession.ProgramTasks列表屬性中刪除ProgramTask,然後將其添加到新會話的相同屬性,NHibernate告訴我已刪除的對象將被重新保存。

如果我只是改變ProgramTask.ProgramSession對象的值,我沒有問題保存。但是,如果我不立即保存,我會得到奇怪的行爲,因爲ProgramSession.ProgramTasks屬性(在兩個會話上)只有在NHibernate會話刷新後纔會同步。

更改ProgramTask.ProgramSession對象而不直接修改列表也會創建無效狀態。以下面的代碼作爲示例:

programTask.ProgramSession = newProgramSession; 
Assert.That(newProgramSession.ProgramTasks.Contains(programTask)); // fails 
Assert.That(!oldProgramSession.ProgramTasks.Contains(programTask)); // fails 

這是在代碼在被執行以後,它假定集合與ProgramSession屬性同步的ProgramTasks更成問題。例如:

foreach(var programTask in programSession.ProgramTasks) 
{ 
    // whatever 
} 

我用來解決這個問題的一個竅門是查詢列表。我不能在任何地方使用它,它顯然是一個壞的解決方案,但它強調了這個問題:

var tasksActuallyInSession = 
    programSession.ProgramTasks 
     .Where(task => task.ProgramSession == programSession) 
     .ToList(); 

有什麼辦法來處理這種情況?最佳做法?難道我做錯了什麼?映射不正確?是否有一些我需要設置的超級祕密NHibernate標誌?

+0

我相信你的意思是把這些屬性放在你在問題中定義的類中。 – tolism7 2009-11-27 14:43:24

+0

你說得對。感謝您的高舉。 – shovavnik 2009-11-27 15:03:42

回答

1

不知道我是否理解你在這裏所做的一切。一些想法:

如果你決定移動ProgramTasks左右,那麼他們是獨立的,不應該使用cascade="all-delete-orphan"映射。如果你這樣做,當你從ProgramSession中刪除它時,NH從數據庫中刪除ProgramTask

使用cascade="none"映射它並自己控制對象的生命週期。 (這意味着:在ProgramSession存儲之前將其存儲,當它不再使用時將其刪除)

不確定這是否也是問題,但請注意,如果您有反向引用,則您的代碼負責使參考文獻保持一致。當然,在存儲到數據庫並加載到空會話後,引用會被清理乾淨,這是因爲數據庫中只有一個外鍵。但這不是它應該完成的方式。 NH不負責管理您的參考。 (它唯一的責任是堅持你在記憶中正在做的事情。)所以你需要在內存中保持一致,並且實現你的業務邏輯,就好像沒有NHibernate一樣。

+0

級聯選項的伎倆。我做了一些更多的研究,並在某些關係上解決了級聯=「刪除」。這種方法的一個警告是我現在需要跟蹤哪些實體是新的,以便我可以決定是否在實體上調用Save()或Update(),而在我使用SaveOrUpdate()之前。所以這實際上加深了我對NHibernate的依賴,但它的工作原理。謝謝。 – shovavnik 2009-11-30 15:41:00