14 February 2009

OpenSession with connection disables second-level cache in NHibernate

I've has this post in my drafts for nearly a year now so I decided I'd finish it off.

I came across an issue when using the second-level cache in NHibernate where none of my objects were being cached and NHibernate was always going to the database for them. What was more odd was the NHibernate debug output suggested the items were being retrieved from the datbase and added to cache but on the next request the items couldn't be resolved in the cache.

Attatching a debugger and stepping through shows a timestamp passed into Cache's Put() method is equal to MinValue which makes it skip the Cache.Add at the last minute (whilst outputting debug messages to the contrary).

Tracking this timestamp back revealed it was created when the session is first openned and was due to my passing in my own connection string rather than letting NHibernate provide one. I assume this is a safeguard because IDs aren't necessarily unique between databases so in that case the cache would perform oddly.

If in your case they are however then you can work around this by casting your ISessionFactory as an ISessionFactoryImplementor. This has an extra overload of OpenSession which takes a IConnection and a ConnectionReleaseMode but doesn't disable the second-level cache.