How to review NHibernate application

time to read 4 min | 704 words

A few hours ago I completed a code review of an application using NHibernate. This is not the first time I am doing such a thing, of course, and I noticed that there are quite a few areas where I tend to have comments in such code reviews.

The following is based on several such code bases that I went through, and contains a partial list of things that you need to watch for.

Mapping

  • The recommended practice is to have each mapping file contain a single class. Having a single mapping file contain multiple classes make it harder to find the matching file, make source control harder to deal with and means that you have to wade through a lot more XML than is healthy for you.
  • Do not specify things in the mapping that you don't have to. Let NHibernate figure out what it can. When you need to change things, you'll be able to do so more easily.
  • If you have logic for selecting which mapping files goes to which session factory, base this logic on easy to follow conventions, such as directory structure, not things that are hard to follow (like processor directives in the XML). In general, avoid having a whole pile of mapping in a single directory, it makes it confusing to deal with.

Session Management

  • If you need to call sessionFactory.OpenSession(), stop and rethink what you are doing. In most scenarios, what you should prefer is a contextual session. This allows you to play some very interesting games (such as multi tenanting the application without letting the application know about it).
  • Be aware of the session that you have. If you do have manual session management, just about the worst thing you can do is to open & close the session per method call.
    In particular, this is a worst practice, in my eyes.
  • public void Save(Customer customer)
    {
    	using(var session = SessionFactory.OpenSession())
    	using(var tx = session.BeginTransaction())
    	{
    		session.Save(customer);
    		tx.Commit();
    	}
    
    }

Transaction Management

  • Use transactions, always.
  • Set the Session Flush Mode to Commit, in order to help enforce that.
  • When you are using a transaction, always wrap it in a using statement.
  • Don't forget to commit :-)
  • Transactions should be opened at the service boundary.

NHibernate Internals Usage

  • Make use of the facilities that NHibernate gives you, but ensure that they are encapsulated well. For example, if you are using IUserType, neither the entity where it is used or the calling code should be aware of that in any way.
  • NHibernate has quite a few extension points that you can use, be aware of them, and the freedom that they give you. However, you should also consider that they are there for special cases, and it is usually better if you can avoid being a special case. I am not saying that you should not extend NHibernate or use the facilities that it gives you to do so. What I am saying is that anything that I have to dive deeply into NHibernate from the application code, I stop and rethink the problem.
  • In particular, you entities should never make any call to the session that created them in order to modify their own state.

Set based thinking

  • NHibernate is OR/M - That is, it bridge between a database and the domain model. There is no good reason to forget that the database is there, and not use it.
  • In particular, things such as filtering and ordering are generally best done at the database level.
  • Overall, remember that the DB is well suited for such tasks, and that doing them at the application level will be a major pain and a hot spot for maintainability issues.

Select N+1

  • Be aware for what is the access pattern of your code, and take measures to reduce the amount of calls to the database.
  • There is no way NHibernate can be fast if you make it call the DB in a loop, where N is any significant number.