Not as lazy as I thought...

by Rob Kitson

I just ran into an unexpected lazy loading issue using NHibernate, so I thought I'd document it here.

Essentially, the domain has a Parent class (called Parent) which has a collection of Child classes (a property named Children which is an IList). The NHibernate mapping is setup as a lazy-loaded collection, which is very performant when the collection of children is small, which you'd typically find when doing unit testing or integration testing. The bottleneck starts showing up as soon as parent.Children.Add(newChild) is called and the number of children is sufficiently large enough to cause a delay while lazily loading the children.

The simple fix is to setup a bi-directional association between the objects and make sure the cascade goes in both directions.  Once that's done, change 'parent.Children.Add(child);' to 'child.Parent = parent;' and flush the changes to the DB. Now, this change will not help very much if you are going to do queries against the Child collection before persisting the changes to the database (since the child won't be in the collection until a query is done to pull the collection out), but it will keep you from pulling all the Children from the database and into memory in order to simply add a new item to the collection. The next time the parent is loaded and the 'Children' property is referenced it will lazily load all the children, including the new record.

To sum it up: If you have a collection that's lazily loaded, and the 'Child' has a reference to the 'Parent', you're better of setting the 'Parent' of the 'Child' than adding the 'Child' to a collection in the 'Parent' since NHibernate is going to load the other 'Child' objects of the 'Parent' before it performs the Add().