I wanted to explore a few options regarding the way we can map inheritance using NHibernate. Here is the model that we are going to use:
And the code that we are going to execute:
using (var session = sessionFactory.OpenSession()) using (var tx = session.BeginTransaction()) { session.CreateCriteria(typeof(Party)).List(); session.CreateCriteria(typeof(Company)).List(); session.CreateCriteria(typeof(Person)).List(); tx.Commit(); }
From now on we are going to simply play with the mapping options to see what we can come up with. We will start with a very simple discriminator based mapping (table per hierarchy):
<class name="Party" abstract="true" table="Parties"> <id name="Id"> <generator class="identity"/> </id> <discriminator column="Discriminator" not-null="true" type="System.String"/> <subclass name="Person" discriminator-value="Person"> <property name="FirstName"/> </subclass> <subclass name="Company" discriminator-value="Company"> <property name="CompanyName"/> </subclass> </class>
Which result in the following table structure:
And the SQL that was generated is:
Select Party
Select Company
Select Person
But that is just one option. Let us see what happen if we try the table per concrete class option:
<class name="Person" table="People"> <id name="Id"> <generator class="identity"/> </id> <property name="FirstName"/> </class> <class name="Company" table="Companies"> <id name="Id"> <generator class="identity"/> </id> <property name="CompanyName"/> </class>
Which result in the following table structure:
And the following queries:
Select Party
No, that is not a mistake, we issue two SQL queries to load all possible parties.
Select Company
Select Person
The inheritance strategy is table per subclass:
<class name="Party" abstract="true" table="Parties"> <id name="Id"> <generator class="identity"/> </id> <joined-subclass table="People" name="Person"> <key column="PartyId"/> <property name="FirstName"/> </joined-subclass> <joined-subclass table="Companies" name="Company"> <key column="PartyId"/> <property name="CompanyName"/> </joined-subclass> </class>
Which result in the following table structure:
And the queries:
Select Party
This is slightly tricky, basically, we get the class based on whatever we have a row in the appropriate table.
Select Company
Select Person
The final option is using unioned subclasses, which looks like this:
<class name="Party" abstract="true" table="Parties"> <id name="Id"> <generator class="hilo"/> </id> <union-subclass table="People" name="Person"> <property name="FirstName"/> </union-subclass> <union-subclass table="Companies" name="Company"> <property name="CompanyName"/> </union-subclass> </class>
Note that it is not possible to use identity with union-subclasses, so I switched to hilo, which is generally much more recommended anyway.
The table structure is similar to what we have seen before:
But the querying is drastically different:
Select Party
Select Company
Select Person
The benefit over standard table per concrete class is that in this scenario, we can query over the entire hierarchy in a single query, rather than having to issue separate query per class.