0

Take the following classes:

public class Employee 
{ 
    public Employee Manager { get; set; }
}

public class ShopFloorEmployee : Employee { ... }

public class OfficeEmployee : Employee { ... }

public class Department 
{
    public Employee Manager { get; set; }
}

and here are the NHibernate mapping files:

  <?xml version="1.0" encoding="utf-8" ?>
  <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
                     namespace="Domain.Entities" 
                     assembly="Domain">
    <class name="Employee">
      <id name="Id" column="Id" type="long">
        <generator class="identity"/>
      </id>
      <discriminator column="Type" type="string"/>
      <many-to-one name="Manager" class="Employee" column="ManagerId" lazy="proxy" />

      <subclass name="ShopFloorEmployee" discriminator-value="ShopFloorEmployee" extends="Employee"/>
      </subclass>

      <subclass name="OfficeEmployee" discriminator-value="OfficeEmployee" extends="Employee"/>
      </subclass>

    </class>
  </hibernate-mapping>

  <?xml version="1.0" encoding="utf-8" ?>
  <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
                     namespace="Domain.Entities" 
                     assembly="Domain">
    <class name="Department">
      <id name="Id" column="Id" type="long">
        <generator class="identity"/>
      </id>
      <discriminator column="Type" type="string"/>
      <many-to-one name="Manager" class="Employee" column="ManagerId" lazy="proxy" />
    </class>
  </hibernate-mapping>

These proxies seem to be causing me problems. For instance, if I load a Department, the Manager of that department (let's call him Bob, who is a ShopFloorEmployee) will be of type EmployeeProxy. Then, in the same session, if I specifically load a list of all ShopFloorEmployees, they will all be of type ShopFloorEmployee except Bob, who will be of type EmployeeProxy. I then can't cast Bob as a ShopFloorEmployee at all, because it has followed a different inheritance path.

The proxies are necassary to avoid recursively loading loads of Employees via their manager each time I load either a Department or Employee.

Am I doing something fundamentally wrong here, or is this a quirk of NHibernate? If it is a quirk then is there a work around? I have considered explicitly closing the session after loading the department but this seems just too hacky.

1
  • If people need it, when I get a moment, I will add the query code. Commented Nov 21, 2012 at 11:33

3 Answers 3

3

A common workaround for this issue is to add a Self property to access the non-proxied type:

public virtual Employee Self
{
   get { return this; }
}

Then you can check Bob.Self is ShopFloorEmployee.

Personally I use inheritance very sparingly and I would use a "role" property here instead of subclassing.

Sign up to request clarification or add additional context in comments.

1 Comment

This was a good solution to fix a problem in an existing domain. If i was designing it from the start, I would use khelland's answer, but this helped me the most in this case.
2

This is a common NHibernate pitfall. Try changing the Manager reference to a No proxy association.

1 Comment

I'm not sure why this dodn't work for me, it is likely I have done something wrong. I'm trying to fix a problem in a complex domain. If I had known this from the start I could have designed it in, and it would have been the right way to go.
1

I had a similar question, see here: fluent nhibernate polymorphism. how to check for type of class

I chose to use a solution based on the Visitor pattern

You do not need to turn off lazy loading nor use funny properties to return the self object

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.