nHibernate Lazy Loading with MVC

By jason

I've been getting to grips with nHibernate recently, having mostly used Entity Framework as my ORM of choice in the past. With nHibernate being the more mature framework, and after hearing things from other developers about how much better nHibernate is, I decided to check it out. To get used to using it, I decided to build a basic MVC website using nHibernate. First of all, I tried using XML mapping, but after having a little bit of trouble getting that up and running, I switched to Fluent nHibnerate (because it also looked cooler).

Rather than using XML, Fluent nHibernate maps directly in class files, with code something like this:

public class PostMap : ClassMap<Post>
{
public PostMap()
{
Id(x => x.Id);
Map(x => x.Title);
Map(x => x.Content);
Map(x => x.CreatedDate);
Map(x => x.ModifiedDate);
References(x => x.User);
}
}

However, when I started actually querying data, I came across the problem that if you had a class that referenced another class (for example, a blog post references a blogger) then when you tried to actually access information about the referenced class (the blogger) on the view side, you'd run into problems. It was because nHibernate 3 uses Lazy Loading by default, which means it only loads information about the blogger when it is specifically requested. The problem in this case was that once the model had been passed to the view, the nHibernate Session that connected it to the database was closed, this meant that you ended up with an error when you tried to do something like this.Model.User.Username, as it was trying to lazy load information on the user but discovering that it couldn't get to the database anymore.

I discovered two solutions after a bit of Googling:

  1. In the mapping class, specify that the reference should not be lazy loaded. This looks like: "References(x => x.User).Not.LazyLoad().
  2. When running a query against the open session, you request the object be explicitly loaded in by using the "Fetch" method. This looks like: "session.Query<Post>().Fetch(p => p.User)".

The second solution is preferable, because it doesn't make the explicit lazy loading system-wide and allows you to handle it on a per query basis.

I realise my post this week was particularly tech heavy, and I'm planning to do a more basic introduction to nHibernate, but I wanted to get this solution out there for anyone who ends up with the same problem!

Related posts