2011-03-08 69 views
4

我有以下類:NHibernate的:獲取具體類型引用的抽象實體的

public abstract class FooBase 
{ 
    public virtual Guid Id { get; set; } 
} 

public class FooTypeA : FooBase 
{ 
    public virtual string TypeAStuff { get; set; } 
} 

public class Bar 
{ 
    public virtual Guid Id { get; set; } 
    public virtual FooBase Foo { get; } 
} 

FooBase和FooTypeA使用表每類層次結構圖案映射。 酒吧被映射這樣的:

public class BarDbMap : ClassMap<Bar> 
{ 
    public BarDbMap() 
    { 
      Id(x => x.Id); 
      References(x => x.Foo) 
       .LazyLoad(); 
    } 
} 

所以,當我打開一個酒吧,其富物業只是一個代理。

如何獲得Foo的子類型(即FooTypeA)?

我已閱讀了很多NH文檔和論壇帖子。他們描述了獲取父類型的工作方式,而不是子類。

如果我嘗試unproxy類,我收到這樣的錯誤: 對象是爲FooBase

回答

1

未初始化的代理獲得「非代理」類型,你可以像這樣添加一個方法來FooBase:

public virtual Type GetTypeUnproxied() { 
    return GetType(); 
} 

當在代理上調用此方法時,將返回基礎對象的類型。

但是,從您的描述看來你似乎試圖在NHibernate會話之外做到這一點,並且這種策略也不適用。要調用代理中調用代理到底層對象的任何方法,它需要實例化,並且只能在NHibernate會話中發生,因爲對象的實際類型存儲在數據庫中(在表的鑑別器列中一類層次繼承策略)。所以我的猜測是,如果您需要稍後檢查類型,則需要確保在關閉會話之前對代理進行初始化。

如果延遲加載Bar-> FooBase關係的原因是FooBase(或派生類型)可能包含大量數據並且您正在使用NHibernate 3,則可以使用lazy properties代替。

+0

嗨,謝謝 - 我想你錯過了我的問題中的最後一句話。當我嘗試unproxy對象時,我收到異常:「對象是FooBase的未初始化代理」。這一切都發生在同一個NH會話內。 – cbp 2011-03-09 00:38:51

+0

嗨,不,這是最後一句讓我相信你試圖在會議以外取消對象的方式。無論如何,如果你正在做會議中的所有事情,我的建議應該可以工作(我自己使用它)。 – Yhrn 2011-03-09 07:25:38

+0

正如你上面所說的,我的建議和Jamie的基本上是一樣的,但我更喜歡只暴露底層對象的類型給你更多的機會繞過代理,從而阻止NHibernate正常工作。 – Yhrn 2011-03-09 07:30:48

2

一個自我屬性添加到FooBase並用它來檢查類型:

public abstract class FooBase 
{ 
    public virtual Guid Id { get; set; } 

    public virtual FooBase Self { return this; } 
} 

用法:

if (Bar.Foo.Self is FooTypeA) { // do something } 
+0

嗨,我認爲這與Yhrn的方法基本相同 - 這個想法是,只要你調用任何虛擬方法(除id之外),該類就不會被取代。然而,當我嘗試這個時,我得到了一個異常:「對象是一個未初始化的FooBase代理」。 – cbp 2011-03-09 00:39:45

+0

請顯示正在加載並堅持對象的代碼。 – 2011-03-09 02:55:18

8

我計算出如何避開我收到的例外。這是一個unproxies FooBase的方法:

public static T Unproxy<T>(this T obj, ISession session) 
    { 
     if (!NHibernateUtil.IsInitialized(obj)) 
     { 
      NHibernateUtil.Initialize(obj); 
     } 

     if (obj is INHibernateProxy) 
     {  
      return (T) session.GetSessionImplementation().PersistenceContext.Unproxy(obj); 
     } 
     return obj; 
    }