Logo

NHibernate

The object-relational mapper for .NET

NHibernate Mapping – Inheritance

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:image

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:

image

And the SQL that was generated is:

Select Party

image

Select Company

image

Select Person

image

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:

image

And the following queries:

Select Party

image

image

No, that is not a mistake, we issue two SQL queries to load all possible parties.

Select Company

image

Select Person

image

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:

image

And the queries:

Select Party

image

This is slightly tricky, basically, we get the class based on whatever we have a row in the appropriate table.

Select Company

image

Select Person

image

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:

image

But the querying is drastically different:

Select Party

image

Select Company

image

Select Person

image

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.


Posted Thu, 09 April 2009 07:43:00 PM by Ayende
Filed under: NHibernate

comments powered by Disqus
© NHibernate Community 2024