2010-01-09 57 views
3

然後我用流利的NHibernate和它的自動映射功能,將下面的簡化POCO類映射:NHibernate的級聯沒有還更新相關實體

public class Webpage 
{  
public virtual int Id { get; set; }  
public virtual string UrlIdentifier { get; set; }  
public virtual WebpageType WebpageType { get; set; }  
} 

public class WebpageType 
{  
public virtual int Id { get; set; }  
public virtual string Name { get; set; }  
} 

我再覆蓋下面的映射明確設置沒有從網頁級聯到WebpageType:

public class WebpageMap : IAutoMappingOverride<Webpage> 
{ 
    public void Override(AutoMapping<Webpage> mapping) 
    { 
     mapping.References(w => w.WebpageType).Cascade.None();  
    } 
} 

對於任何PUR NHibernate的讀者,這裏是通過液態生成的XML映射:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true"> 
    <class xmlns="urn:nhibernate-mapping-2.2" name="EveryPage.Core.Domain.Webpage, EveryPage.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Webpage`"> 
    <id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" unsaved-value="0"> 
     <column name="Id" /> 
     <generator class="identity" /> 
    </id> 
    <property name="UrlIdentifier" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="UrlIdentifier" /> 
    </property> 
    <many-to-one cascade="none" class="EveryPage.Core.Domain.WebpageType, EveryPage.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="WebpageType"> 
     <column name="WebpageType_id" /> 
    </many-to-one>  
    </class> 
</hibernate-mapping> 


<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true"> 
    <class xmlns="urn:nhibernate-mapping-2.2" name="EveryPage.Core.Domain.WebpageType, EveryPage.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`WebpageType`"> 
    <id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" unsaved-value="0"> 
     <column name="Id" /> 
     <generator class="identity" /> 
    </id> 
    <property name="Name" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Name" /> 
    </property> 
    </class> 
</hibernate-mapping> 

當我測試更新不會通過網頁級聯到WebpageType時,問題就出現了,基本上他們做了!

我有以下測試:

[Test] 
    public void Assert_SaveOrUpdate_On_Webpage_Does_Not_Cascade_Update_To_WebpageType() 
    { 
     // Get the existing webpage. 
     webpage = _webpageRepository.Get("~/testwebpage1.aspx"); 

     // Update the WebpageType. 
     const string webpageTypeName = "qwerty test"; 
     webpage.WebpageType.Name = webpageTypeName; 

     // Save the changes. 
     Assert.DoesNotThrow(() => _webpageRepository.SaveOrUpdate(webpage)); 

     // We need to flush the changes to the store for it to execute the changes. 
     Assert.DoesNotThrow(() => NHibernateSession.Current.Flush()); 

     // Remove the webpage and tag from the level 1 cache so we force a trip to the store on our next check. 
     NHibernateSession.Current.Evict(webpage); 

     // Check that the webpageType has not been updated. 
     webpageType = _webpageTypeRepository.Get(webpageType.Id); 
     Assert.AreNotEqual(webpageTypeName, webpageType.Name); 
    } 

以上測試被包裹在一個全局事務。

測試失敗,NHibernate會執行相關WebpageType的名稱更新。刪除和保存(創建新)級聯可正常工作,不會級聯。

我是否錯過了級聯和/或是否有我的邏輯/測試問題。

任何幫助/建議表示讚賞。謝謝。

回答

3

如果您試圖阻止您的應用程序意外更改WebPageType的屬性,我認爲通過在映射中將WebPageType標記爲ReadOnly可以更輕鬆,更安全地實現此目的。那麼你不需要通過處理其所有關聯中的級聯來保護它。

+0

乾杯Noel,我會試試:) – j3ffb 2010-01-12 11:42:30

0

你的倉庫是做什麼的?確保它不會在網頁類型上運行saveorupdate。如果不是,那麼我沒有看到這種行爲的任何明顯的解釋。

+0

嗨布萊恩,沒有我的倉庫只是保存網頁。 – j3ffb 2010-01-12 10:59:04

3

我認爲這是對級聯意味着什麼的誤解。

在你的例子中,NHibernate會更新你WebPageType的Name屬性,不管你設置了級聯。如果你仔細想想,NHibernate庫如何通過WebPage實例中的關聯來處理屬性的值,或者直接完成?

NHibernate中級聯的設置說明了如何處理實體之間的關聯,而不是如何處理每個實體內部的實際值。例如,您可以設置刪除級聯,這會在實體本身被刪​​除時自動刪除關聯的實體。

事情的博客文章可能會使事情更清楚一點,或者至少作爲工作某種參考:http://ayende.com/Blog/archive/2006/12/02/NHibernateCascadesTheDifferentBetweenAllAlldeleteorphansAndSaveupdate.aspx

+0

嗨,Liedman,我明白你在說什麼,但是,如果我只保存網頁對象,爲什麼NH還會對WebpageType的多對一​​關聯進行保存?那不是一種級聯保存? – j3ffb 2010-01-12 11:03:28

+2

這是關於NHibernate如何工作的最常見的錯誤之一。在NHibernate中,對持久化對象的更改(例如,使用查詢從數據庫加載到ISession中的實例,獲取/加載或僅使用保存持久化)自動*保存到數據庫(除非您回滾事務)。 來自文檔:「應用程序可以操縱事務持久化實例(即由ISession加載,保存,創建或查詢的對象),並且當刷新ISession時,持久狀態的任何更改都會持久化」(自動刷新除非你另有說明。) – Liedman 2010-01-12 14:33:08