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