Ang3lFir3 – Life as a Code Poet

August 4, 2009

Table Per Class Inheritance Mapping with Fluent nHibernate

Filed under: C#, Fluent NHibernate, NHibernate, ORM, Patterns — Tags: , , , , , — ang3lfir3 @ 10:45 am

This is the first in a short series of posts I am working on. While reading through NHibernate in Action I thought to my self that I should create these same examples of Inheritance mapping using Fluent nHibernate to show how simple these mappings can be.

The three types of Inheritance mappings that are mentioned on page 92 of NHibernate in Action are :

  • Table Per Concrete Class Model
  • Table Per Class Hierarchy
  • Table Per Subclass

I will be using the example from NHibernate in Action to illustrate the mappings. This post covers the most basic and often most common example, Table Per Class. In Table per concrete class inheritance mapping we discard polymorphism and inheritance from the relational schema and create as the name suggests a single table for each concrete class. This means that the DateCreated , Number, and Owner properties of the base class will be reflected in each table. This can be dangerous as these column’s datatypes must now stay in sync across the two tables. If a change needs to be made to the schema you will have to find all the tables that inherit from BillingDetails and edit their schemas independently. This is not necessarily a problem when dealing with a few classes but can be come a problem in a larger and more complex model.

TablePerClassFiles

Here you can see that in this case I have only two mapping files. One for each inheritor.

Below you can see the Fluent nHibernate mapping classes that show how simple this mapping is.

  public class BankAccountMap : ClassMap<BankAccount>
  {
    public BankAccountMap()
    {
      Id(x => x.Id, "BankAccount_Id");
      Map(x => x.Number);
      Map(x => x.Owner);
      Map(x => x.DateCreated);
      Map(x => x.BankName);
      Map(x => x.RoutingNumber);
    }
  }

  public class CreditCardMap : ClassMap<CreditCard>
  {
    public CreditCardMap()
    {
      Id(x => x.Id, "CreditCard_Id");
      Map(x => x.Number);
      Map(x => x.Owner);
      Map(x => x.DateCreated);
      Map(x => x.Type);
      Map(x => x.ExpirationMonth);
      Map(x => x.ExpirationYear);
    }
  }

Which maps to the following nHibernate mapping XML:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="">
  <class name="TablePerClass.Model.BankAccount, TablePerClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`BankAccount`" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" type="Int32" column="BankAccount_Id">
      <generator class="identity" />
    </id>
    <property name="Number" type="String">
      <column name="Number" />
    </property>
    <property name="Owner" type="String">
      <column name="Owner" />
    </property>
    <property name="DateCreated" type="DateTime">
      <column name="DateCreated" />
    </property>
    <property name="BankName" type="String">
      <column name="BankName" />
    </property>
    <property name="RoutingNumber" type="String">
      <column name="RoutingNumber" />
    </property>
  </class>
</hibernate-mapping>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="">
  <class name="TablePerClass.Model.CreditCard, TablePerClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`CreditCard`" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" type="Int32" column="CreditCard_Id">
      <generator class="identity" />
    </id>
    <property name="Number" type="String">
      <column name="Number" />
    </property>
    <property name="Owner" type="String">
      <column name="Owner" />
    </property>
    <property name="DateCreated" type="DateTime">
      <column name="DateCreated" />
    </property>
    <property name="Type" type="Int32">
      <column name="Type" />
    </property>
    <property name="ExpirationMonth" type="String">
      <column name="ExpirationMonth" />
    </property>
    <property name="ExpirationYear" type="String">
      <column name="ExpirationYear" />
    </property>
  </class>
</hibernate-mapping>

And finally here you see the relational model that this maps to. The base class properties are stored as columns of each table.
TablePerClassSchema

kick it on DotNetKicks.com

5 Comments »

  1. I enjoy this site, it is worth me coming back

    Comment by Kelli Garner — September 25, 2009 @ 9:22 pm

  2. Hi,

    I was wondering if you could tell me, when using this method, say you had a parent entity which had as a collection IList, how could you map that parent entity?

    Many thanks

    Matt

    Comment by Matt Brailsford — January 27, 2010 @ 8:10 am

  3. Ooops, that screwed up my code example, but it was IList<BillingDetails>

    Comment by Matt Brailsford — January 27, 2010 @ 8:11 am

    • In short… Table Per Class does not work well for Polymorphism from the db schema perspective… to allow for mapping IList<BillingDetails> you should probably choose another strategy… most likely Table Per Subclass or if the number of types/differences in types is small then possibly Table Per Class Hierarchy

      Comment by ang3lfir3 — January 27, 2010 @ 12:58 pm

      • Cool. Many thanks for pointing me in the right direction.

        Matt

        Comment by Matt Brailsford — January 27, 2010 @ 1:30 pm


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.