NHibernate:获取具体类型的引用抽象实体

时间:2011-03-08 07:17:24

标签: 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; }
}

使用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的未初始化代理

3 个答案:

答案 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代替。