colinramsay.co.uk

NHibernate's Inverse Attribute

15 Mar 2008

This post specifically refers to the use of the inverse attribute on Many-To-One relationships, such as a Category with many products. That's simply because it's the one I'm dealing with right now, and it's the one I've been using most commonly.

I've never really "got" the inverse attribute, so I'm going to try and write it out in order to understand it better. I've used it plenty, but often blindly, and probably not in the right way for my situation. Let's assume that we create a Category:

Category category = new Category{Name="Lovely Category"};
session.Save(category);

Very good; the Category is saved to the database and all is well. Now, let's say that at a later time we wish to add a Product to this Category. Here's our Product:

Product product = new Product{Name = "Sweet Product"};

We need to make a two-step operation before saving it:

product.Category = category;
category.Products.Add(product);

In other words, the Product needs to know about the Category and the Category needs to know about the Product. It is not sufficient to do one or the other. Think about it outside of the bounds of NHibernate if that doesn't immediately make sense. Now, to the saving of the Product, and where the Inverse attribute comes in. Assuming you have a standard bidirectional one-to-many relationship set up in your mapping files, you'll have something like this on your Category:

<bag name="Products" cascade="all" inverse="true|false">
	<key column="CategoryId"/>
	<one-to-many class="Product"/>
</bag>

And something like this one your Product:

<many-to-one name="Category" class="Category" column="CategoryId"/>

Here's the long and short of it. If you want to do this (parent):

session.Save(category);

Then you need to have inverse=true on your bag. If you want this to work (child):

session.Save(product);

You need inverse=false on the bag. Actually that even makes sense to me now.