Reputation: 5333
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:
Upvotes: 2
Views: 413
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:
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