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