Reputation: 2573
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.
Upvotes: 0
Views: 1189
Reputation: 3143
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
Upvotes: 1
Reputation: 49291
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.
Upvotes: 3
Reputation: 18112
This is a common NHibernate pitfall. Try changing the Manager
reference to a No proxy association.
Upvotes: 2