Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,124 | Comments: 45,474

filter by tags archive

NHibernateComplex relationships

time to read 3 min | 541 words

Originally posted at 11/18/2010

I got an interesting question today (I am teaching my NHibernate course now).

The tabular structure is similar to this:


But the desired object structure is:


That is quite different than the tabular model, but it is actually very easy to handle this with NHibernate.

Here are the mapping for the Address entity. We use the <join/> tag to have an entity that spans more than a single table:

<class name="Address"
  <id name="Id">
    <generator class="identity"/>
  <property name="City" />

  <join table="PeopleAddresses" >
    <key column="AddressId"/>
    <property name="IsDefault"/>
    <property name="ValidFrom"/>
    <property name="ValidTo"/>


We then map the Person, using standard many-to-many mapping for the addresses:

 <class name="Person"

   <id name="Id">
     <generator class="identity"/>
   <property name="Name" />

   <bag name="Addresses" table="PeopleAddresses" inverse="true">
     <key column="PersonId"/>
     <many-to-many class="Address" column="AddressId"/>

There is just one thing thing to be aware of, you can’t add new addresses via the Person.Addresses collection, because the PeopleAddresses table has more data in it than just the keys. Presumably, you are handling this in some other fashion already.

All in all, this is a pretty elegant solution.

More posts in "NHibernate" series:

  1. (19 Nov 2010) Complex relationships
  2. (27 Jun 2010) Streaming large result sets
  3. (25 May 2009) Why do we need to specify the query type twice?
  4. (20 Mar 2009) Avoid identity generator when possible
  5. (26 Mar 2007) Nullable DateTime Issues
  6. (08 Jan 2007) Fetching multiply collections in one roundtrip


Victor Kornov

Pardon my ignorance, but how "you can’t add new addresses via the Person.Addresses collection" relates to the conclusion of "this is a pretty elegant solution"? All I can think of is having another set of classes\mappings just to be able to save the person's address. That's not elegant in my books.

Ayende Rahien


You need to map the PersonId column on the PeopleAddresses, and then you can threat this as a standard Many To One.

The scenario that was brought up was were there was another way of handling that, so I didn't bother with that


The tabular model and the object structure in almost all cases will be quite different, with one modelling data and the other modelling behaviour. This is something that most ORMs don't handle as elegantly as the code above.


What about using <idbag?


Oops, it seems my comment is stripped.

What about using idbag?


If you really want flexibility given the table structure above and still want to handle inserts.

Create a sql view that fits the exact mapping structure and let the view deal with the inserts appropriately.

Fabio Maulo

Can I refactorize that DB ? or it is untouchable ?


Good, old-fashioned blog entry. Interesting case.

Frans Bouma

I'm with Victor, this isn't elegant at all. It's also wrong: PersonAddresses is an objectified relationship (in Object Role Modeling / NIAM terms), and this means it's an entity by itself. Just because it defines a m:n relationship between person and address doesn't make it an entity which doesn't exist, and the limitation that you can't persist new addresses shows that.

I fail to see why PersonAddresses has to be wiped under the rug: its name is perhaps badly chosen, but it is a valid entity, that you don't want to program with it, is really ignorance: because the entity exists in the domain, you have to deal with it, and which is the reason you have to deal with it too only in 'some other fashion'.

The m:n relationship between person and addresses is readonly, over the objectified relationship. I do recall having a discussion with Fabio about this some time ago on nhusers.

Nestor Rodriguez

This challenge is an evidence of how NHibernate can deal with bad databases design but refactor is a must !.

Comment preview

Comments have been closed on this topic.


  1. RavenDB 3.5 whirl wind tour: You want all the data, you can’t handle all the data - about one day from now
  2. The design of RavenDB 4.0: Making Lucene reliable - 3 days from now
  3. RavenDB 3.5 whirl wind tour: I’ll find who is taking my I/O bandwidth and they SHALL pay - 4 days from now
  4. The design of RavenDB 4.0: Physically segregating collections - 5 days from now
  5. RavenDB 3.5 Whirlwind tour: I need to be free to explore my data - 6 days from now

And 14 more posts are pending...

There are posts all the way to May 30, 2016


  1. RavenDB 3.5 whirl wind tour (14):
    29 Apr 2016 - A large cluster goes into a bar and order N^2 drinks
  2. The design of RavenDB 4.0 (13):
    28 Apr 2016 - The implications of the blittable format
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series



Main feed Feed Stats
Comments feed   Comments Feed Stats