57726

Inheritance and lazy loading in NHibernate

Question:

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.

Answer1:

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.

Answer2:

This is a common <a href="http://weblogs.asp.net/ricardoperes/archive/2012/08/02/nhibernate-pitfalls-inheritance-and-proxies.aspx" rel="nofollow">NHibernate pitfall</a>. Try changing the Manager reference to a <a href="http://ayende.com/blog/4378/nhibernate-new-feature-no-proxy-associations" rel="nofollow">No proxy association</a>.

Answer3:

I had a similar question, see here: <a href="https://stackoverflow.com/questions/13484939/fluent-nhibernate-polymorphism-how-to-check-for-type-of-class/13543390#13543390" rel="nofollow">fluent nhibernate polymorphism. how to check for type of class</a>

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

Recommend

  • Elasticsearch highlight matches in HTML without breaking syntax
  • Packaging a Python library with an executable
  • php imagick gif resize all frame
  • How to convert react JSX files to simple JavaScript file [offline transformation]
  • Python multiprocessing using a lock or manager list for Pool workers accessing a global list variabl
  • C, Little and Big Endian confusion
  • openOptionsMenu() across android versions
  • Passing Objects to fragment without argument
  • Stop or Detection dll injection loadlibrary
  • Overlaying text on video with required angle using FFMPEG
  • Why is the list of files for a range of commits different from the aggregation of the lists of files
  • ffmpeg: How to concat audio files and add background music in a single command?
  • Converting a self subquery to a self join
  • How to set http status code when responding to servlet client from Filter class-method in tomcat
  • yii rewrite url with many sub categories
  • Unity Resources.load() won't work with external dll
  • content must have a ListView whose id attribute is 'android.R.id.list'
  • opencv deskewing a contour
  • Controller or RestController
  • how to specify different css for ie
  • How to define something in JavaScript [closed]
  • Calculate time from document
  • Neo4j…how to get a visual representation of my data?
  • 'url' requires a non-empty first argument. The syntax changed in Django 1.5, see the docs
  • Amazon Elastick BeanStalk error: Failed to create the AWS Elastic Beanstalk application version
  • How to use Streams api peek() function and make it work?
  • Stacked bar chart with continuous time-axis as x-axis
  • How to decleare char *const argv[] in swift [duplicate]
  • Functions by reference or by variable, which to use when?
  • How to get rgb from transparent pixel in js
  • Bitrate JWplayer
  • Accessing Arguments, Workflow Variables from custom activities
  • WPF custom control and direct content support