Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate: Get concrete type of referenced abstract entity

Tags:

nhibernate

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

like image 533
cbp Avatar asked Mar 08 '11 07:03

cbp


2 Answers

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;
    }
like image 200
cbp Avatar answered Oct 14 '22 04:10

cbp


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 }
like image 44
Jamie Ide Avatar answered Oct 14 '22 03:10

Jamie Ide