You gotta love NHibernate. But sometimes there are little quirks the drive you nuts—at least until you understand how NHibernate handles things. We ran into one such "hiccup" the other day.
Our objective was to have a parent object contain a list of child objects. Simple enough. Problem is, we didn't want the child to know about or have a reference back to the parent. But all of the simple example code that we found for NHibernate and Fluent NHibernate kept showing the bidirectional reference.
Inverse To The Rescue…Almost
The whole idea about the inverse attribute, specifically Inverse=true, is so that the parent "owns" the collection. We thought this was enough. Nope. We kept getting issues where the database would throw an exception because NHibernate was trying to insert a null "parent ID" value into the child table.
After digging deeper, we came up with the following feature matrix related to the value:
Inverse=False means that:
- Child object is inserted first (null parent id).
- Parent object is inserted second.
- Child is then updated with parent id.
- Parent id in child table must be nullable.
- Child doesn't need a reference to the parent.
Inverse=True means that:
- Parent inserted first.
- Child inserted (with parent id value populated) second.
- Parent id in child table can be (but need not be) nullable.
- Child must have a reference to the parent.
Unfortunately, we couldn't have it both ways. We wanted the parent to have a reference to the child AND to have the parent id column in the child table to be "not null". In the end, we decided on Inverse=True.
When working with aggregates, the guidance is to access everything through the aggregate root. So, when we create a child object, we simply call myParentObject.CreateChild() and we have the CreateChild method enforce the bidirectional reference.
The solution above is for one of our legacy codebases. Using newer CQS [Young] style approaches, we don't really have to worry about this.