NHibernate: Mapping Application Domain

Mapping Class Inheritance


There are three different approaches to represent a class inheritance hierarchy.

1) Table per concrete class

This approach uses one table for each (non-abstract) class. All class properties, including inherited properties, can be mapped to columns in the table.

In NHibernate, use a <class> declaration for each concrete class, specifying a different table attribute for each.

Problems with this approach:

  • Limited support for polymorphic associations (where subclasses are inherited from a base class).
  • Polymorphic queries are also problematic. A query against the base class must be executed as several SQL select statements, one for each concrete subclass.
  • A change to a column in the base class would result in a column change in multiple tables.

2) Table per class hierarchy

An entire class hierarchy is mapped to a single table. The table includes columns for all properties of all classes in the hierarchy.

This strategy is both simple and good for performance.

The concrete subclass represented by a particular row must be identified by a unique value (a type discriminator column).

In NHibernate, use the <subclass> element to define this class hierarchy mapping for each subclass and map the base class using a <subclass> element. Specify, the unique row identifier column using the <discriminator> element in the base class mapping and discriminator attribute in the subclass mapping.

Problems with this approach:

  • Database columns for properties declared by subclasses must be declared to be NOT NULL and this can cause a problem from the point of view of data integrity.

3) Table per subclass

Every subclass that declares persistent properties (including abstract classes and even interfaces) has its own table.

The table here contains columns only for each non-inherited property (each property declared by the subclass) along with a primary key that is also a foreign key of the base class table. The two rows are linked together by their shared primary key value.

In NHibernate, you use the <joined-subclass> element to indicate a table per subclass mapping. NHibernate will then use an outer join when querying the database.

Advantages of this approach:

  • Relational model remains normalised.
  • Schema changes are straightforward.