Vasea
Vasea

Reputation: 5333

Dealing with large class inheritance hierarchies in NHibernate

My model looks like this:

where InsurancePolicy is an abstract class which is the base class for all concrete implementations of insurance policies. AbcInsurancePolicy , DefInsurancePolicy , etc are implementations which correspond to a certain insurance products. Sometimes I define other abstract classes for subgroups of policies with a subset of common fields (like VehicleInsurancePolicy).

I mapped this classes using a "Table per subclass, using a discriminator" strategy. The InsurancePolicy table contains about 60 fields, and each joined table adds from 10 to 30 fields. I used this strategy because:

The InsurancePolicy is used often as a many-to-one relationship in other entities like Payment, Document etc.

NHibernate generates a lot of left-outer-joins when querying for InsurancePolicy because it doesn't know the type. This is very inefficient as I have a lot of tables to join. The problem becomes even worse when lazy-loading many-to-one properties containing an InsurancePolicy because it is used quite a lot in my model. The concrete implementations are used rarely, only in edit/details scenarios where it is specified the actual type and only the needed tables are joined.

Then I used a combination of discrimator + join. Thus the InsurancePolicy table contains the information about the type. Unfortunately a "join" mapping doesn't support lazy-loading. I tried setting fetch="select", however these generates N+1 selects when querying for multiple insurance policies.

// select from 1 table, "join" class must be lazy-loaded on access
Session.Get<InsurancePolicy>(5) 

// select includes a join, since we explicitly specified a concrete type
Session.Get<SomeConcreteInsurancePolicy>(5)

So my questions are:

  1. Is there a way to extend NHibernate to make it work like above?
  2. Is there another way of mapping these large / complex class hierarchies?

Upvotes: 2

Views: 413

Answers (1)

Diego Mijelshon
Diego Mijelshon

Reputation: 52745

Based on this:

The concrete implementations are used rarely, only in edit/details scenarios

I recommend that you break up InsurancePolicy in two:

  • InsurancePolicy, containing only the properties from the current base class
  • PolicyDetails, an abstract base class for the hierarchy.

There's a one-to-one relationship between those two classes.

The beauty of this is that you don't have to change anything else (except a minor change in the policy edit views, to point them to the new relationship)

Upvotes: 2

Related Questions