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

cbp*_*cbp 5 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; }
}
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的未初始化代理

cbp*_*cbp 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;
    }
Run Code Online (Sandbox Code Playgroud)


Yhr*_*hrn 1

要获得“unproxied”类型,您可以向 FooBase 添加如下方法:

public virtual Type GetTypeUnproxied() {
    return GetType();
}
Run Code Online (Sandbox Code Playgroud)

当在代理上调用此方法时,将返回底层对象的类型。

然而,从您的描述来看,您似乎正在尝试在 NHibernate 会话之外执行此操作,并且这也不适用于此策略。要调用代理上的任何方法,其中调用被代理到底层对象,它需要实例化,并且只能在 NHibernate 会话中发生,因为对象的实际类型存储在数据库中(在表的鉴别器列中) -每类层次结构继承策略)。所以我的猜测是,如果您稍后需要检查类型,您需要确保在关闭会话之前初始化代理。

如果延迟加载 Bar->FooBase 关系的原因是 FooBase(或派生类型)可能包含大量数据,并且您正在使用 NHibernate 3,则可以使用延迟属性