Custom Lazy-loadable Business Collections with NHibernate

October 22, 2007

I was at VSLive Las Vegas last week and one of my talks was on NHibernate development.  One of the guys who was in my session came up to me and asked "how do I create my own custom collection that I can use in NHibernate that still lets me do lazy loading?"

The core of the problem is that NHibernate's lazy-loading prefers to do interfaces for public colleciton properties.  At runtime, NHibernate sets in a proxy that implements the appropriate collection interface and your code never knows the difference.  It's that proxy class that you get at runtime that implements the lazy loading logic -- if you access a property on that collection and the data hasn't been loaded yet, the proxy goes out and gets it before returning the appropriate value(s).

That's great until you need to do some custom work as part of one of the collection methods or until you need a new method.  The only way you can do that is to plug in a custom collection -- but then you lose all ability to do lazy loading.

To get around this problem, I created an abstract class in my Com.Benday.NHibernate library called LazyLoadableBusinessCollection.  When you need a custom collection, extend from this class and you'll still be able to do lazy loading.  (BTW, I came up with this class in probably January of 2007 and it's taken me this long to get around to actually blogging about it.)

How does it work and how do you use it?:

1. Lazy loading happens via the Elements property on LazyLoadableBusinessCollection.

private IList m_elements;
protected IList Elements
{
get
{
if (m_elements == null) m_elements = new List();

return m_elements;
}
set
{
m_elements = value;
}
}

2. Instead of mapping the and letting NHibernate create your collection, use to create an instance of your custom collection, and map the to LazyLoadableBusinessCollection's Elements property

                                       







3. All the IList features still work because LazyLoadableBusinessCollection forwards all IList, ICollection, IEnumerable, and IEnumerable properties and methods to the appropriate method/property on the Elements property.

#region IList Members

public virtual int IndexOf(T item)
{
return this.Elements.IndexOf(item);
}

public virtual void Insert(int index, T item)
{
this.Elements.Insert(index, item);
}

public virtual void RemoveAt(int index)
{
this.Elements.RemoveAt(index);
}

public virtual T this[int index]
{
get
{
return this.Elements[index];
}
set
{
this.Elements[index] = value;
}
}

#endregion

Here's a link to download a sample application that demonstrates the LazyLoadableBusinessCollection.  Check out the following files: RestaurantCollection.cs, Person.cs, Person.hbm.xml, and LazyLoadableBusinessCollection.cs.

Let me know if you have any questions.

-Ben

Categories: good-stuff nhibernate tech
Tags: c-sharp