2010-11-05 54 views
5

我有一個類似這樣的域類。我希望NHibernate在保存當前值LastUpdate插入/更新時,以便我可以在查詢中使用它,但從數據庫中檢索Foo時忽略它,並讓對象本身重新計算實際訪問它時的值。使用流利NHibernate映射一個只讀屬性沒有設置器

public class Foo { 
    public DateTime LastUpdate { 
     get { 
      /* Complex logic to determine last update by inspecting History */ 
      return value; 
     } 
    } 
    public IEnumerable<History> History { get; set; } 
    /* etc. */ 
} 

我對Foo映射是這樣的:

public class FooMap : ClassMap<Foo> { 
    Map(x => x.LastUpdate) 
     .ReadOnly(); 
    HasMany(x => x.History); 
    // etc... 
} 

我認爲ReadOnly()是我想做到這一點,但是當我嘗試創建一個SessionFactory我得到以下異常:

Error: FluentNHibernate.Cfg.FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
---> NHibernate.PropertyNotFoundException: Could not find a setter for property 'LastUpdate' in class 'Foo'.

該屬性沒有setter,因爲它不應該設置,只能從讀取。是ReadOnly()在這裏做的正確的事情?如果不是,什麼?

(NHibernate的v3.0b1,功能NHibernate V1.1)

+0

只讀() ;僅在生成的映射xml流中設置LastUpdate屬性的insert =「false」和update =「false」屬性。 – tolism7 2010-11-07 00:13:58

回答

12

ReadOnly指示流利NHibernate不尋找這個屬性的變化,這不等同於編譯器世界中的只讀屬性。你的財產在NHibernate的眼中不是隻讀的,因爲你期望它從數據庫中填充。你需要做的是告訴NHibernate,它應該通過與屬性名稱相同(小寫)的私有字段來訪問該屬性的值。

Map(x => x.LastUpdate) 
    .Access.Field(); 

有幾個選擇使用Field,你用哪一個取決於你如何命名你的私人領域。

+2

我實際上並不想從數據庫中填充屬性,它是在getter中動態計算的。我只是希望它被保存到數據庫,以便我可以查詢它。 – 2010-11-08 15:58:16

+6

如果Nhibernate沒有填充它,它將不知道保存它,因爲它不知道該值是否以及何時發生更改。提供的兩種解決方案都完全相同,並按照您的描述進行。 NHibernate可以通過字段訪問變量,所以你不需要setter。當您訪問getter時,該值將被動態計算。當你更新NHibernate會保存值。 NHibernate從db中填充它的事實應該是無關緊要的 - 直到你訪問你不知道/關心,當你訪問它時,它的值將被計算。看看Nhibernate「初始化」是否有幫助。 – Sisyphus 2010-11-09 06:30:59

+0

@Sisyphus這個解釋有很大幫助。謝謝。 – 2010-11-12 19:06:37

2

至於NHibernate的推移,可以映射到一個字段,即成員變量所以Nhibernate的可以直接訪問成員變量。所以你可以創建一個像_lastUpdate這樣的可以直接映射的成員變量。 Nhibernate現在將有一個變量來使用,你可以在你的getter中單獨控制這個值,因爲NHibernate將不再使用屬性getter。它會保存值並檢索它,但是檢索到的值並不重要,因爲只要通過getter訪問,就可以重新計算它。同樣沒有getter或setters的私有變量。

在普通的HBM中,您只需映射access =字段即可。每個人都這樣做。顯然Fluent並不簡單。我不使用流利......

編輯...

找到任何映射私人支持字段看似永遠向前的目標是在你的版本,以...

+1

這與Fluent NHibernate一樣簡單:'Map(x => x.LastUpdate).Access。Field()' – 2010-11-08 15:12:37

0

只需添加一個空的私人二傳手到類:

 private set { } 

我還添加屬性和註釋來記錄我的意圖(做出ReSharper的快樂):

 [UsedImplicitly] 
     // ReSharper disable once ValueParameterNotUsed 
     private set { }