Hi all!
I'm new to nhibernate and I'm faced to some subclassing problems which I can't solve on my own - so maybe somebody can help me with these. In my application I have different types of users: IndependentVolunteer, EmployedVolunter, COEmployee. An IndependentVolunteer is not employed at any organization, while an EmployedVolunteer is employed at a VolunteerOrganization and a COEmployee is employed at a CharitableOragnization. To make it easier for me to explain I'll post my code first.
In code for the users this looks as follows (for simplicity I shortened some parts):
Code:
public abstract class User 
   {
      private Guid      _ID;
      private string      _UserName;
      public User(...) { }
               /* public properties for ID and UserName come here */
        }
public class IndependentVolunteer : User
   {
      public IndependentVolunteer(...) : base(...) { }
   }
public class EmployedVolunteer : User
   {
      private VolunteerOrganization      _Organization;
      public EmployedVolunteer(...) : base(...) { }
      /* public property for Organization comes here */
   }
public class COEmployee : User
   {
      private CharitableOrganization      _Organization;
      public COEmployee(...) : base(...) { }
      /* public property for Organization comes here */
   }
The code for the organizations:
Code:
public abstract class Institution
   {
      private string      _Name;
      private Guid      _ID;
      public Institution(...) { }
      
      /* public properties for ID and Name come here */
   }
public class VolunteerOrganization : Institution
   {
      public VolunteerOrganization(...) : base(...) { }
   }
public class CharitableOrganization : Institution
   {
      private string   _StatuteURL;
      public CharitableOrganization(...) : base(...) { }
      /* public propertiy for StatuteURL comes here */
   }
Finally, the configuration is
Code:
<hibernate-mapping auto-import="true" assembly="NHibernateTest" namespace="NHibernateTest" xmlns="urn:nhibernate-mapping-2.0">
   <class polymorphism="explicit" name="User" table="T_Users" discriminator-value="0">
      <id name="ID" access="property" column="ID" type="Guid">
         <generator class="guid.comb" />
      </id>
      <discriminator column="Type" type="Int32" not-null="true" ></discriminator>
      <property access="property" not-null="true" name="UserName" type="String" column="UserName" />
      <subclass discriminator-value="1" name="IndependentVolunteer">
         
      </subclass>
      <subclass discriminator-value="3" name="COEmployee">
         <many-to-one class="CharitableOrganization" column="InstitutionID" access="property" not-null="true" name="COrganization"></many-to-one>
      </subclass>
      <subclass discriminator-value="2" name="EmployedVolunteer">
         <many-to-one class="VolunteerOrganization" column="InstitutionID" access="property" not-null="true" name="VOrganization"></many-to-one>
      </subclass>      
</class>
</hibernate-mapping>
<hibernate-mapping auto-import="true" assembly="NHibernateTest" namespace="NHibernateTest" xmlns="urn:nhibernate-mapping-2.0">
   <class polymorphism="explicit" name="Institution" table="T_Institutions" discriminator-value="0">
      <id name="ID" access="property" column="ID" type="Guid">
         <generator class="guid.comb" />
      </id>
      <discriminator column="Type" type="Int32" not-null="true" ></discriminator>
      <property access="property" not-null="true" name="Name" type="String" column="Name" />
      <subclass discriminator-value="1" name="VolunteerOrganization">
         
      </subclass>
      <subclass discriminator-value="2" name="CharitableOrganization">
         <property access="property" not-null="true" name="StatuteURL" type="String" column="StatuteURL" />
      </subclass>      
   </class>
</hibernate-mapping>
Now I have the following problem: a user should login into the system via his username and password. To find the matching user in the database, I use the CreateCriteria method:
Code:
Criteria = Session.CreateCriteria(typeof(User));
         Criteria.Add( Expression.Like("UserName", "user2" ) );
         Collection = Criteria.List();
The user with username "user2" is of type EmployedVolunteer. When calling the List() method, I receive an exception telling me "Object with id: xy was not of the specified sublcass: CharitableOrganization". The assigned organization for the requested EmployedVolunteer is of type VolunteerOrganization - so why is it trying to load it as CharitableOrganization?
Anyway, I found out the using the Find() method instead works:
Code:
Collection = Session.Find( "FROM User as U WHERE U.UserName LIKE 'user2'" );
returns one object of type EmployedVolunteer.
Can anybody explain me the difference? Are my mapping files wrong? Is there a better way to model the class hierarchy? I'm faced to this problem at some points within my code - unfortunately there are points where the Find() method does not work either, so any help would be greatly appreciated.
Thanks in advance
Markus