I was reading a “nhibernate in Action” and found some interesting things. I will post more from this book once I am through .
Common mistakes done while using nhibernate
If you read this section, you may just have receive one of these performance complains we talked
about. Here are some common mistakes you may have done and tips to help dramatically improve
your application’s performance (and make the end-users happier).
By the way, you should consider writing performance tests at an early stage to avoid waiting for the
end-user to tell you that your application is too slow. And don’t forget to also optimize your database
(adding the correct indexes, etc.).
A mistake that some new NHibernate developers commit is that they create the session factory
more than required. This is a very expensive process. Most of the time, it is done once at the start of
the application. Avoid keeping the session factory at a place that lives shorter than your application
(like keeping it in a web page request).
Another common mistake, related to the fact that NHibernate makes it so easy to load entities, is
that you may load more information than you need (without even knowing it). For example,
associations and collections are fully initialized when lazy loading is not enabled. So even when
loading a single entity, you may end fetching a whole object graph. The general advice here is to
always enable lazy loading and to carefully write your queries.
Another related problem, arising when enabling lazy loading, is the n+1 select problem. For more
details, read chapter 8, section 8.6.1, “Solving the n+1 selects problem”. By the way, a nice way to
spot this issue early is to measure the number of queries executed per page; you can easily achieve
that by writing a tool to watch logs from NHibernate.SQL at DEBUG level. If it is higher than a certain
limit, you have got a problem to solve and do it immediately, before you forget what is going on in
You may also measure other performance-killer operations (like the number of remote calls
per page) and global performance information (like the time it takes to process each page).
You should also try to load the information you need using the minimal number of queries
(however, avoid expensive queries like those involving Cartesian product). Note that it is generally
more important to minimize the number of entities loaded (row count) than the number of fields
loaded for each entity (column count).
Chapter 8 describes many features that can help you writing optimized queries.
Now, let’s talk about a less known issue. This one is related to the way NHibernate works. When
you load entities, the NHibernate session keeps a number of information about them (for transparent
persistence, dirty checking, etc.). And when committing/flushing, the session uses this information to
perform the required operations.
There is a specific situation where this process can be a performance bottleneck: When you load a
lot of entities to update only few of them, this process will be slower than it should be. The reason is
that the session will check all these entities to find those that must be updated. You should help it
avoiding this waste by evicting unchanged entities or using another session to save changed entities.
As a last resort, consider using the 2nd level cache (and the query cache) to hit the database less
often and reuse previous results. Read chapter 6, section 6.3, “Caching theory and practice”, for more details on the pros and cons of this feature.
You can download this book from here