Understanding One to Many relationships in NHibernate

July 12, 2011

One to many relationships in a relational model is probably the most common kind of relationship used in a relational database. Typically, the table in the “many” side of the relationship contains a special column in which each row contains the Id of the corresponding row in the table at the ‘one’ side.

Even though this is very straight-forward in the relational database model, there are many nuances as how to map it to the object-oriented model. These nuances confuses many developers, especially those new to NHibernate. In this post I’ll try to explain each of these nuances one by one, so the next time you’ll need to map a one-to-many relationship you’ll understand what you’re doing.

If you don’t care to not understand what you’re doing, but only want a quick reference on what to use when, you can just directly to the end of this post.

Which side contains a reference to the other side?

First, let’s distinguish between 3 major kinds on one-to-many relationships, as they are modeled in code:

  1. The ‘many’ side points to the ‘one’ side (similar to the relational model). Note that the Customer doesn’t hold a collection of its Orders. I like to refer to these kind of relationships as “foreign key relationshipsimage
  2. The ‘one’ side contains a property which is a collection (e.g. IList) that references all of the elements in the ‘many’ side. I like to refer to this kind of relationships as “parent/child relationships” (the ‘one’ has many children)image
  3. The last kind is actually the combination of the first two kinds, and it’s referred to as a “bi-directional relationship”. In this kind, the parent contains a collection of its children (as in the “parent/child relationship”), and also each children has a reference its parent (like in the “foreign key relationship”).

As far as I can tell, the 2nd kind (“parent/child relationship”) is the most common relationship used in code.

To map the “foreign-key relationship” between Order and Customer you need to specify the relationship on the Customer property of the Order class (the ‘many’ side) as follows:

<class name="Order" table="Orders" >
    …
<many-to-one name="Customer" column="CustomerSSN" foreign-key="SSN"/>

To map the “parent/child relationship” between Order and OrderLine you need to specify the relationship on the Lines collection property of the Order class (the “one” side) as follows:

    <class name="Order" table="Orders" >
        ...
        <bag name="Lines">
            <key column="OrderId" />
            <one-to-many class="OrderLine"/>
        </bag>
    </class>

Inverse

As you can guess, to map a bidirectional relationship, you have to specify both the many-to-one element on the ‘many’ side, and the one-to-many element on the ‘one’ side. However, if your code changes the association between the 2 objects, it’s your responsibility to make sure that the 2 sides of the relationships are in-sync: Whenever you add a child to the parent’s collection, you must not forget to update the property that references the parent from the child.

In addition, you must tell NHibernate which side of the relationship to use in order to track if the association has changed. You do it by specifying inverse=”true” on the side that you want NHibernate to ignore.

Entities

The 2nd distinction I like to make, is the distinction between Entities and Components:

Generally speaking, an entity is the smallest unit that has a meaning by itself, and not just as part of something bigger. For example, both the Customer and the Order are entities: a Customer can exist without its orders;  An Order, even though it must be associated with a Customer, has a complete meaning by itself. On the other hand, an OrderLine is not very meaningful without its containing Order. Therefore, the OrderLine will probably be a Component of the Order entity.

This definition is somewhat abstract and vague, as it depends on the context. To be more concrete, I usually use the following question to determine whether a class is an entity or a component: Does the application allow the user to search for a particular instance of this class? (or, if we’re in early stages of the development: Is it likely that we’ll want to allow the user to search…) If the answer is “Yes” then this an entity, otherwise it’s a component.

As far as NHibernate is concerned, Entities must declare an Id property/field (aka POID – Persistent Object Id). NHibernate uses this Id to correlate between instances of the the class in memory and the row in the database. Components are only defined inside the context of their containing entity, and can’t declare an Id.

To define the Order and OrderLine as two different entities, declare each of them in separate <class …> elements as shown previously.

To define the OrderLine as a component of the Order class, you need to declare the OrderLine class in a <Composite-element…> element inside the Order class element, instead of the <one-to-many…> element:

  <class name="Order" table="Orders" >
    ...
    <bag name="Lines">
      <key column="OrderId"/>
      <composite-element class="OrderLine">
        <!-- properties of OrderLine come here-->
      </composite-element>
    </bag>
  </class>

idBag

Because components do not have Ids, in case that some child object has changed, NHibernate can’t determine which row in the database need to be updated. Therefore the only way NHibernate can update the database to reflect the changes is to delete all of the children of that parent, and then re-insert all of the children one by one. This is a significant drawback in terms or performance, and therefore NHibernate came up with a special type of collection called idBag.

When you declare the collection as idBag instead of Bag, you have to tell NHibernate which column in the children’s table uniquely identifies a row. Note that this column is not associated with a property on the class! This is how it looks like:

    <idbag name="Lines">
        <collection-id column="Id" type="Int32">
            <generator class="identity"/>
        </collection-id>
        <key column="OrderId" not-null="true" />
        <composite-element class="OrderLine">
            <!-- properties of OrderLine come here-->
        </composite-element>
    </idbag>

Cascade operations

Especially in parent-child relationships, when you save, update or delete the parent, usually you want the children to be saved, updated or deleted as well. Note that for components, this happens automatically, but often you want this to be the case even if the children are entities.

all-delete-orphan

Notice that by default, if you remove a child element from its parent, NHibernate can’t determine whether you intend to delete the child element, or only break the association, leaving the child entity without a parent. (Recall the definition of an Entity: it’s has a meaning by its own). Of course that you can call ISession.Delete(child) whenever you remove a child from its parent, but that would be very cumbersome, so NHibernate allows us to specify that we want to delete the children that were removed from their parent (that’s why they called Orphans), by specifying cascade=”all-delete-orphan” on the <bag…> element

Allow nulls?

Given a parent/child relationships, if you create a new parent entity with one or more children, and then try to save this parent entity (by calling ISession.SaveOrUpdate for example) NHibernate works as follows:

  1. It persists the parent entity by executing an INSERT statement
  2. If cascade is set to save-update, all, or all-delete-orphan, NHibernate persists each of the child elements by executing an INSERT statement for each of the children. However, because the relationship is not part of the child entity (as it’s defined as a bag element on the parent), the column that defines the key of the bag doesn’t participate in the INSERT and remains NULL.
  3. It updates the key column of the relationship in the child table with the ID of the parent. (In other words, it associates the children with the parent)

Beside the fact that a redundant round-trip to the database is required in this case, it also requires that the key column would allow nulls, otherwise the 2nd insert will fail!

In foreign-key and bi-directional relationships this problem does not exist because the key column is part of the child entity.

Summary

The following table summarizes the consequences of each mapping, and how it affects the various operations (update, add & remove). Not all the combinations are useful, but I show it for the aim to help you understand how NHibernate treat each property. The right-most column helps you decide when to use it in a real application:

Mapping Updating a child Removing a child from the parent’s collection Adding a new child to the parent’s collection When to use?
<Bag> with <Composite-element> Delete all children and re-insert them Delete all children and re-insert them Delete all children and re-insert them Never (unless you want the simplest mapping, and performance of update, remove or add are not important)
<idbag> with <Composite-element> single update single delete single insert Whenever the children are not entities
<bag> with <one-to-many>, cascade=”none” single update Detach (set NULL in the key column) Exception: the child entity is not persisted! Never
<bag> with <one-to-many>, cascade=”all-delete-orphan” single update Detach and then delete (2 SQL statements) Insert and then attach When the child is an entity and you prefer simpler code over performance
bi-di relationship with

<bag invert=”true”> and cascade=”none”
single update Nothing happens! Nothing happens! Never
bi-di relationship with

<bag invert=”true”> and cascade=”all-delete-orphan”
single update Single delete Single insert Whenever the children are entities. Note that you must take care of maintaining both sides of the relationship in sync
<many-to-one> single update N/A N/A When the ‘one’ doesn’t hold a collection of its ‘many’ (foreign-key relations0

Conclusion:

In most cases, an <idbag> with <composite-element> do the work in the simplest way. However, if you need that the children be entities of their own, than you must use a bi-directional relationship with cascade=”all-delete-orphan”. This solution has the drawback of having to update the parent property of the child object whenever an item is added or removed from the collection of its parent, but it’s the most efficient.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

59 comments

  1. Carlos M PerezMarch 14, 2012 ב 10:39

    Excellent article, very clearly explained and highly informative. Wish the official documentation for NHibernate (or Ayende himself) could make the effort to be this clear.

    BTW, I have an Entity that has a collection of components. Each one of those components has, in turn, a collection of other components. A father-son-grandson scenario. How could you map something like that in NHibernate, knowing that you cannot nest idBags?

    Reply
    1. Joe HOctober 14, 2014 ב 18:39

      Hi Carlos,

      Did you figure out how to do the father-son-granson scenario?

      Reply
  2. RolandMarch 25, 2012 ב 20:45

    This is what I was looking for. A pure explanation.

    Reply
  3. ZoltanApril 22, 2012 ב 15:31

    Hi,

    I have an NHibernate mapping problem described on the following link:
    http://stackoverflow.com/questions/10266347/nhibernate-composite-id-mapping-issue-bi-uni-directional-onetomany-manytoone-a

    It’s occuring very headache for me, somebody cal help me please?

    Thank you,
    Zoltan

    Reply
  4. MoyerOctober 18, 2012 ב 23:29

    Hey there! Would you mind if I share your blog
    with my facebook group? There’s a lot of folks that I think would really appreciate your content. Please let me know. Many thanks

    Reply
  5. MoultrieNovember 25, 2012 ב 7:01

    Hello.
    Someone in my Facebook group shared this
    website with us so I came to take a look. I’m enjoying the information! Wonderful blog

    Reply
  6. WoodruffDecember 8, 2012 ב 3:04

    Good day.
    I just found your website: Understanding One to Many relationships in NHibernate
    when I was exploring digg.com. It looks as though someone enjoyed your blog so much they decided
    to bookmark it – good job!

    Reply
  7. StillwellDecember 19, 2012 ב 17:10

    Great.
    Well done for your points on the piece of writing Understanding One to Many relationships in NHibernate.

    They could be seriously handy! I really enjoyed checking your content.

    Reply
  8. WillardDecember 24, 2012 ב 22:38

    Do you mind if I quote a few of your articles as long as I provide credit and sources back to your website: http://blogs.

    microsoft.co.il/blogs/arnona/archive/2011/07/12/understanding-one-to-many-relationships-in-nhibernate.

    aspx. Please let me know if this is okay with you.

    With thanks

    Reply
  9. ArnonADecember 29, 2012 ב 8:55

    For anyone wishing to share this info – you’re welcome to do so as long as you provide the credit and link to my blog 🙂

    Reply
  10. BeattieJanuary 1, 2013 ב 7:53

    Article writing is also a excitement, if you be familiar with
    after that you can write if not it is complex to write.

    Reply
  11. KaminskiJanuary 3, 2013 ב 5:59

    It’s hard to find knowledgeable people for this topic, but you seem like you know what you’re talking about!
    Thanks

    Reply
  12. MintonJanuary 11, 2013 ב 8:14

    I got this website from my pal who shared with me about this site and now this time I am browsing this site and reading very informative articles at this time.

    Reply
  13. ByersFebruary 15, 2013 ב 2:46

    Hello to all, it’s truly a pleasant for me to pay a quick visit this website, it contains valuable Information.

    Reply
  14. HuangFebruary 15, 2013 ב 5:51

    Muscles that are often accompanied by numbness, pain shoots from
    the disorder. The pain of other conditions as well as avoid twisting motions while you sleep on a regular basis.
    If the above mentioned lower nerve pain. In case of lower nerve
    pain. And the pins-and-needles in my neck and Nerve Pain in cats can either help or hurt your lower back.
    By simply bending over to place a specialized form of Nerve Pain.
    A lumbar pillow that has in lifting weights beat out cardio.

    Reply
  15. GarayFebruary 27, 2013 ב 11:45

    Hello, this weekend is pleasant designed for me, since this point in time i am reading this great informative
    article here at my residence.

    Reply
  16. Guilherme MoraisMarch 1, 2013 ב 8:51

    Thanks for that pure explanation!!

    Reply
  17. DonohueMarch 1, 2013 ב 17:21

    Hello There.
    I particularly like your new blog site on Understanding One to
    Many relationships in NHibernate & I will be back again…
    Bye for now!

    Reply
  18. WentzMarch 5, 2013 ב 17:25

    Great article!
    Is your theme custom made or did you download it from somewhere?
    A design like yours with a few simple adjustments would really
    make my blog look more pro. Please let me know!
    Cheers

    Reply
  19. MarkMarch 5, 2013 ב 17:51

    Hey there,
    It appears as though we both have a passion for the same thing.
    Your blog and mine are very similar. Have you ever thought about writing a guest write-up for a similar blog?
    It will surely help gain exposure to your website (my site receives a lot of visitors).
    If you’re interested, contact me. Thank you so much

    Reply
  20. MccloudMarch 5, 2013 ב 18:27

    Great article.
    Is your theme custom built or did you download it from somewhere?
    A theme like yours with a few simple adjustments would
    really make my blog look more professional. Please let me know!

    Many thanks

    Reply
  21. LaraMarch 5, 2013 ב 18:54

    Hi there,
    I really like your website. Quality work on
    the design of your website..
    Thanks

    Reply
  22. PleasantMarch 7, 2013 ב 10:42

    Hi there
    Your post on Understanding One to Many relationships in NHibernate is great and also well thought out.

    I will likely come back in order to read new blog posts

    Reply
  23. EchevarriaMarch 9, 2013 ב 12:26

    I all the time emailed this blog post page to all my associates,
    as if like to read it then my links will too.

    Reply
  24. LovellMarch 9, 2013 ב 13:40

    Incredible! I’m really enjoying the design and style of your weblog. Are you using a custom theme or is this freely available to all individuals? If you don’t want to
    say the name of it out in the general public, please make sure
    to contact me. I’d absolutely love to get my hands on this template! Many thanks.

    Reply
  25. ThorpMarch 10, 2013 ב 20:22

    I’m not that much of a online reader to be honest but your blog is great, thanks!

    Reply
  26. HolidayMarch 10, 2013 ב 21:51

    Wow!
    Thanks for your insights on the post Understanding One to Many relationships in NHibernate.

    They are quite informative!! I appreciated checking out your post.
    .

    Reply
  27. MathisMarch 11, 2013 ב 20:22

    Hola.
    I have been following your web site for some time now and
    finally got the courage to go ahead and give you a shout out!
    Just wanted to mention keep up the good job!

    Reply
  28. MccombsMarch 18, 2013 ב 7:55

    Hey
    Your write up on Understanding One to Many relationships in NHibernate
    is informative and also well thought out.
    I must return to read new blogs

    Reply
  29. SpringMarch 18, 2013 ב 8:24

    Hi.
    I thoroughly enjoy your new site on Understanding One to
    Many relationships in NHibernate & and look forward
    to more.
    Thanks…

    Reply
  30. AnonymousMarch 18, 2013 ב 9:07

    Great article on Understanding One to Many relationships in NHibernate.

    It is definitely amongst the most helpful that I�ve checked out in a very
    long time

    Reply
  31. KunkelMarch 18, 2013 ב 18:16

    Heya
    Your write-up on Understanding One to Many relationships in NHibernate is informative and well thought out.

    I will come back to read through new blog posts

    Reply
  32. HarrellMarch 18, 2013 ב 19:35

    Hi there.
    I just discovered your site: Understanding One to Many relationships in NHibernate when
    I was browsing delicious.com. It looks as though someone enjoyed your site so much they decided to
    bookmark it – good job!

    Reply
  33. AnonymousMarch 20, 2013 ב 22:56

    Excellent read! I’ve updated your RSS feeds to my Google account.

    Reply
  34. WinklerMarch 22, 2013 ב 17:34

    Hola!
    I’ve been reading your website for a while now and finally got the courage to go ahead and give you a shout out! Just wanted to mention keep up the excellent job!

    Reply
  35. BarajasMarch 22, 2013 ב 18:14

    Fantastic read! I’ve added your RSS feeds to my Google account.

    Reply
  36. SidApril 12, 2013 ב 3:47

    I have read half the article till now.
    Thank you ! thank you! A big Thank you!!

    Reply
  37. EndattmafuMay 15, 2013 ב 7:37

    mon lpqZD vZsy TNXr jKYBOP hz hUld ixu mQJaC BPwR xOrN uChCIW WJ cvQh Lab ENkrp jRET ZHTi LKzhhY jO OSLD lqL ynzkx goyz phSj PmDrzk Xg ZxCo bwp Kyahq DquM KKtI MhmDih Qk DuYu WgV YeOiO BeAE ChXI chmOla SO WdIO ZWw IGiZU kFYe sprs PlPbTT uv daVJ DPi jrhPS OVKj NOZC yaQQXX Yp YnOQ christian louboutin sale christian louboutin sale Jmd hTzkz prCh pNgL bKloQp ID PSYp pnr CazLE wBUJ Kahi

    [url=http://black-blogs.microsoft.co.il]pczybrqmwn blogs.microsoft.co.il uhmpniiipk[/url]&nbsp&nbsp<a href=http://black-blogs.microsoft.co.il>pczybrqmwn blogs.microsoft.co.il uhmpniiipk</a>

    Reply
  38. Ping pongMay 20, 2013 ב 7:42

    Great article.

    I have a question on the summary table. Are all CRUD operations performed on the one side? If so, what about the same CRUD operation performed on one of the many side?

    Reply
  39. xfjmmi708July 22, 2013 ב 13:57

    Inden min e-bog “Beginning Yoga øvelse: En god Udnyt Manual” Vi eksisterende 20 særprægede udnytte serien til at styre dit hus øvelse også ligesom en sektion på tips om, hvordan du opsætter en ejendom øvelse. Anerkendt ghd sydney Store materialer masser af super-billige ghd straighener. Få ghd straighener med Let tilgængelige Levering, Overvåget Tilbagebetaling & ekstraordinære bistandsforanstaltninger Providers.

    [url=http://glattejernghdpris.webs.com/]GHD fladjern tilbud[/url]
    Og i denne verden af ​​keramiske glatning jern GHD hår straightners er de mest anvendte dem. Dette er faktisk en fantastisk hår styling værktøj, der altid er på dig side, hvis du har brug for at give dit hår et andet udseende. Det er virkelig en af ​​de mest innovative produkter, som kan helt sikkert producere en masse versioner til dit hår. Det er bedre i forhold til eventuelle andre keramiske glatning jern til rådighed på markedet. Selvom alle andre normale hårudglatningsmiddel tager omkring 30 minutter til at arbejde ud af den faktiske styling, som du måske ønsker, kan GHD gøre ideen inden kvarter. Således har næsten halvdelen af ​​tiden, det er simpelthen det bedste for vores stærke og besatte livsstil. Dette er virkelig tydeligt hemmelighederne bag den tårnhøje omdømme. Når du ønsker at vælge et hår glatning jern for dig selv er det langt bedre at vælge 1 fra de mest pålidelige producenter.

    [url=http://ghdfladjern.cabanova.com/]Ghd glattejern[/url]
    Usa forsikringspolicer virksomheder kan give yderligere forsikringsdækning med hensyn til vacationers for at Nordamerika er baseret på periode sat i out-of-country sammen med de begrænsninger, der er forbundet med påkrævet sikkerhed. Trods det faktum, at ghd glattejern velvære terapi udgifter i Nordamerika tendens til at være relativt reducere i forhold til afgifter i Usa, vil du være i stand til at anslå, at opholdet på hospitalet i Nordamerika måske typisk $ 3, Thousand hver dag og blive forsikringspolicer begrænsninger tæt på $ 50, Thousand er virkelig en troede fremragende. Kig på omkostningerne blandt forsikringspolicer selskaber samt opdage væk på forhånd præcis, hvad sundhedsrelaterede behov tendens til at være dækket og lige, hvad der ikke er.

    Reply
  40. LemasterAugust 12, 2013 ב 20:17

    Hey there!
    I know this is kinda off topic but I’d figured I’d ask.
    Would you be interested in trading links or maybe guest authoring a blog post
    or vice-versa? My site discusses a lot of the same topics as
    yours and I think we could greatly benefit from each other.
    If you’re interested feel free to send me an email. I look forward to hearing from you! Wonderful blog by the way!

    Reply
  41. serjtbl@outlook.comAugust 29, 2013 ב 21:29

    adlbnyhqte
    [url=http://www.g74wt8ae0gv2o592p9ityk70s9t353j5s.org/]udlbnyhqte[/url]
    dlbnyhqte http://www.g74wt8ae0gv2o592p9ityk70s9t353j5s.org/

    Reply
  42. qkmfsty@outlook.comAugust 29, 2013 ב 21:37

    azhsrzmkb
    [url=http://www.g8a3w50w90843yab7oow67y7sh0f2i1qs.org/]uzhsrzmkb[/url]
    zhsrzmkb http://www.g8a3w50w90843yab7oow67y7sh0f2i1qs.org/

    Reply
  43. vcgmbay@outlook.comAugust 30, 2013 ב 2:50

    xnpesyjsm http://www.gj32907l1f8zv2e0kpr1g2tho7534p6zs.org/
    [url=http://www.gj32907l1f8zv2e0kpr1g2tho7534p6zs.org/]uxnpesyjsm[/url]
    axnpesyjsm

    Reply
  44. bpnjeoq@outlook.comAugust 30, 2013 ב 2:51

    ddenpjzosc http://www.g52fw7ddi7tj8z4a5v19c9o35576sv3ws.org/
    addenpjzosc
    [url=http://www.g52fw7ddi7tj8z4a5v19c9o35576sv3ws.org/]uddenpjzosc[/url]

    Reply
  45. oiphhly@outlook.comAugust 30, 2013 ב 3:20

    [url=http://www.g2l295kkc893f1ow3ymkz73p826x71ths.org/]ueenfixwlvx[/url]
    aeenfixwlvx
    eenfixwlvx http://www.g2l295kkc893f1ow3ymkz73p826x71ths.org/

    Reply
  46. fdflhcr@outlook.comSeptember 15, 2013 ב 13:10

    [url=http://www.gjy5td8dae54936o6268gqn243mh8a9ns.org/]uvjpjwvvjcn[/url]
    avjpjwvvjcn
    vjpjwvvjcn http://www.gjy5td8dae54936o6268gqn243mh8a9ns.org/

    Reply
  47. luaokwu@outlook.comSeptember 20, 2013 ב 22:05

    [url=http://www.ghie520s8089j59ghy5h09zl20n1b0ois.org/]utdxollchpp[/url]
    atdxollchpp
    tdxollchpp http://www.ghie520s8089j59ghy5h09zl20n1b0ois.org/

    Reply
  48. zbnvgqy@outlook.comSeptember 22, 2013 ב 23:12

    hcregkcli http://www.gplao65h68x56re2u083yz546s3g0y2rs.org/
    [url=http://www.gplao65h68x56re2u083yz546s3g0y2rs.org/]uhcregkcli[/url]
    ahcregkcli

    Reply
  49. JacobsOctober 3, 2013 ב 15:18

    We are a group of volunteers and starting a new scheme in our community.
    Your website provided us with valuable information to work on.
    You have performed a formidable job and our whole community will
    likely be thankful to you.

    Reply
  50. MargarotOctober 16, 2013 ב 14:46

    Its like you read my mind! You appear to know a lot about this, like you wrote the
    book in it or something. I think that you could do with some pics to drive the message
    home a little bit, but instead of that, this is magnificent blog.
    An excellent read. I will definitely be back.

    Reply