NHibernate中對同一個對象的Lazyload要設置一致

在NHibernate中出於性能的考慮,經常使用Lazyload的方式來加載關聯的對象,關於什麼是Lazyload,以及怎麼使用,可以參見博客園中的文章,比如:http://www.cnblogs.com/lyj/archive/2008/10/28/1321494.html

常用NHibernate.ByteCode.Castle動態代理來實現Lazyload,使用該程序集會在運行時創建實體對應的代理類,如果實體使用了繼承關係,並通過NHibernate來映射,那麼動態代理類在類型轉換時會有問題。

比如在C#中定義了一個Node類,然後有個State類繼承自Node類,然後有Flow.Node引用了這個類,同時我還在Task.Node中引用了這個類。並且在默認情況下啓用了Lazyload。在通過Flow對象獲得Node對象時,會返回'Castle.Proxies.NodeProxy'對象,而這個對象是沒辦法轉換成State對象的,所以會拋出如下的異常:

Unable to cast object of type 'Castle.Proxies.NodeProxy' to type 'Xxx.Core.Model.Definition.State'.

那麼怎麼辦呢,只有不使用Lazyload,所以我將Flow.Node的加載方式改爲立即加載,然後這個異常就沒有了。但是今天在調用另外的方法,然後在調用Flow.Node時,又出現了這個異常,這讓我十分鬱悶,我明明指定了Flow.Node是立即加載的,那麼怎麼還是會被系統轉換爲NodeProxy了呢?

經過研究發現,應該是Task.Node沒有被設置爲立即加載的原因。我在調用Flow.Node之前,調用了Task對象,所以NHibernate根據Task的Mapping設置,將Node設置爲動態代理類,同時將Node緩存到了Session中,然後再調用Flow.Node時,系統就會先從緩存中查找是否有對應的Node對象,結果正好有NodeProxy的緩存,所以就直接返回NodeProxy給Flow.Node了,系統根本沒有檢查Flow.Node是不是立即加載還是懶加載。

所以要解決這個異常的話,有兩個辦法,一種是將Task.Node也設置成爲立即加載,那麼就不會有NodeProxy對象在緩存中。另外一種辦法就是不在Task中引用Node對象,我採用的是第二種方法,在Task中,其實我只需要Task.NodeId就夠了,不需要再加載Node對象進來。

總的來說,如果在NHibernate中用到了繼承類,如果同時用到了Lazyload,那麼在轉換類型時就可能拋出異常。解決辦法就是將Lazyload取消,改爲立即加載。如果有多個實體引用了該對象,那麼就需要將這個對象的引用的Lazyload方式設置爲一致的,對不使用Lazyload或者減少對對象的引用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章