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.
Just to add another way of saying it, inverse=true means… “hey – the other side manages this collection!”
Be careful using bags though, if you set inverse=false on the many end of a bag NHibernate doesn’t know what was added or deleted and has to delete and re-persist each item. This can be horrendous for large collections.
I think idbags are better in this scenario because you can uniquely define the row.
This burned me in the past.
Ben ScheirmanAs much as i love your screencasts – your blog right-aligned text is Horrible. I cannot read anything longer then on line and it is very hard to see the topics.
In the name of good design…
In any case, the content is great though!
andriyThere you go andriy, seeing as you were so nice about the content, you can have a nice fresh design!
Colin Ramsay