NHibernate: Get concrete type of referenced abstract entity

南笙酒味 提交于 2020-01-03 10:57:34

问题


I have the following classes:

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 and FooTypeA are mapped using the table-per-class-heirarchy pattern. Bar is mapped like this:

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

So when I load a Bar, its Foo property is only a proxy.

How do I get the subclass type of Foo (i.e. FooTypeA)?

I have read through a lot of NH docs and forum posts. They describe ways of getting that work for getting the parent type, but not the subclass.

If I try to unproxy the class, I receive errors like: object was an uninitialized proxy for FooBase


回答1:


I worked out how to avoid the exception I was receiving. Here is a method that 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;
    }



回答2:


Add a Self property to FooBase and use that to check the type:

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

    public virtual FooBase Self { return this; }
}

Usage:

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



回答3:


To get the "unproxied" type you could add a method like this to FooBase:

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

When this method is invoked on a proxy the type of the underlying object will be returned.

However, from your description it seems you are trying to do this outside of the NHibernate session and that won't work with this strategy either. To invoke any method on the proxy where the call is proxied to the underlying object it needs to be instantiated and that can only happen within the NHibernate session since the actual type of the object is stored in the database (in a discriminator column for the table-per-class-hierarchy inheritance strategy). So my guess is that you need to make sure that the proxy is initialized before closing the session if you need to check the type later.

If the reason for lazy loading the Bar->FooBase relation is that FooBase (or a derived type) might contain large amounts of data and you are using NHibernate 3 you could use lazy properties instead.



来源:https://stackoverflow.com/questions/5229510/nhibernate-get-concrete-type-of-referenced-abstract-entity

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!