我有以下课程:
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; }
}
Run Code Online (Sandbox Code Playgroud)
FooBase和FooTypeA使用table-per-class-heirarchy模式进行映射.Bar的映射方式如下:
public class BarDbMap : ClassMap<Bar>
{
public BarDbMap()
{
Id(x => x.Id);
References(x => x.Foo)
.LazyLoad();
}
}
Run Code Online (Sandbox Code Playgroud)
所以当我加载一个Bar时,它的Foo属性只是一个代理.
我如何获得Foo的子类类型(即FooTypeA)?
我已经阅读了很多NH文档和论坛帖子.他们描述了获取父类型的工作方式,而不是子类.
如果我尝试取消该类的代理,我会收到如下错误: object是FooBase的未初始化代理
我想出了如何避免我收到的异常.这是一个解开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;
}
Run Code Online (Sandbox Code Playgroud)
要获得“unproxied”类型,您可以向 FooBase 添加如下方法:
public virtual Type GetTypeUnproxied() {
return GetType();
}
Run Code Online (Sandbox Code Playgroud)
当在代理上调用此方法时,将返回底层对象的类型。
然而,从您的描述来看,您似乎正在尝试在 NHibernate 会话之外执行此操作,并且这也不适用于此策略。要调用代理上的任何方法,其中调用被代理到底层对象,它需要实例化,并且只能在 NHibernate 会话中发生,因为对象的实际类型存储在数据库中(在表的鉴别器列中) -每类层次结构继承策略)。所以我的猜测是,如果您稍后需要检查类型,您需要确保在关闭会话之前初始化代理。
如果延迟加载 Bar->FooBase 关系的原因是 FooBase(或派生类型)可能包含大量数据,并且您正在使用 NHibernate 3,则可以使用延迟属性。