tags:

views:

741

answers:

3

I believe this is a common question / problem but have not been able to find a good clean concise answer.

The Problem

How to map entities that appear to have an inheritance relationship:

Company
  Supplier
  Manufacturer
  Customer

However, a Supplier can be a Manufacturer.

or

Person
  Doctor
  Patient
  Employee

Where a Patient can be a Doctor or can be an Employee.

Suggestion: Use Roles

In discussions on the NHibernate forums, the response is often that this is multiple inheritance.

http://forum.hibernate.org/viewtopic.php?t=959076

They solution suggested is to use composition or to use "Roles". However, I cannot find any examples or explanation on how exactly to do that.

"Favor composition over inheritance." Remember that little goodie from class? In this instance I have to agree that you are trying multiple inheritance-- not possible in C# or Java (yet). I, personally, would encourage you to think about re-modeling so you have a Person object and a person has a one-to-many collection of Roles.

+3  A: 

You probably want to consider using the Roles. So a Role will have a set of Persons. Or a Person will have a set of Roles or both. This would probably imply that there is an Association class that maps persons to roles.

Define a Person class with all properties that are common to people. Then define a Role super class and DoctorRole, PatientRole and EmployeeRole sub classes (Assuming that each role has different properties).

The Person class can have a Collection of roles defined and the Role class can have a Collection of people defined. Or it might be easier to create an Association class, lets call it PeopleRole.

This page explains how to do the mapping so that PeopleRole is a composite element. Look at the Order/Product/LineItem example. Your Person is like Order, PeopleRole is like LineItem and Role is like Product.

Vincent Ramdhanie
The piece that I failed to grasp was the DoctorRole, PatientRole, etc subclasses! The link is helpful too! Thanks
quip
+2  A: 

It seems to me that this is more a question around how to model a domain well, rather than an NHibernate mapping issue.

Once you've sorted out your domain modelling, I think you'll find the NHibernate mapping falls out relatively easily.

One place to look to get your head around the idea of modeling Roles is to look for "Color Modeling" - Jeff de Luca has some resources, though the idea originated with Peter Coad

The basic idea is to separate the identity of a participant from the role they play in an activity.

For example, you might have a Person object that captures the identify of a particular person.

Then, a completely separate object "Student" that captures the additional information to record the enrolment of a person as a student. Each instance of Student would have a reference to the person enrolled. A single person may be related to many "Student" records, one for each distinct enrolment.

In parallel, you could have a distinct "Tutor" object that records employment details when someone is hired to teach students in one-on-one situations. The Tutor object captures the additional details around how someone is employed as a tutor.

This structure gives you great flexibility - one person (Joe Bloggs) may just be a student, another person (Jane Doe) may just be a tutor, and a third (Chuck Norris) may be both.

Also, introducing another role (Lecturer, Marker, Administrator) becomes easier because the additions don't require changes to existing objects.

Bevan
Thanks for your answer. It was helpful in understanding from a modeling perspective. You're right, it is more of a domain modeling question than NHibernate specific.
quip
+1  A: 

I came across a bit more commentary you might find relevant:

In a blog post on the Naked Objects blog a few different approaches are outlined discussing the pros and cons of each.

  • Using an 'Any' association mapping
  • Modelling roles as classes
rohancragg
That article looks promising. I didn't have time to read it in depth, but looks to be a good find.
quip