The Second Level Cache
This article explains how to use the second level cache
NHibernate Caches
NHibernate, by default, uses a first-level cache, or session-level cache. It means that, inside the same session, you can ask for the same object twice, and the database will be queried just once.
In addition, NHibernate also supports a second-level cache, or sessionfactory-level cache. It can cache object data among different sessions, drastically reducing the need for database queries.
While the second level cache is very powerful, we do not recommend using it as a crutch. Your applications should not require the second level cache in order to gain acceptable performance. Using the cache in this manner usually indicate of a general problem in the way the data is handled in the application, with the cache acting as a band-aid. You should always be aware of how much each operation costs.
Choosing the second level cache
NHibernate has several second level caches to choose from. The most common one is the SysCache, which is using the ASP.Net cache to store the cached data. This cache is a local cache, and should not be used in a web farms scenarios. For those scenarios, the MemCached cache should be used. For more information about the different cache provider implementations, please refer to the NHibernate cache provider documenation.
Before starting to use the second level cache, make sure that you understand how it works! It can become particulary dangerous when your database is changed from outside NHibernate: either manually or by other applications. See the NHibernate documentation on caching.
Using the second level cache
Within ActiveRecord configuration (Enabling the SysCache with an expiry of 300 seconds)
<config> <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" /> <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" /> <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" /> <add key="hibernate.connection.connection_string" value="Data Source=.;Initial Catalog=myapp_db;Integrated Security=SSPI" /> <add key="hibernate.cache.provider_class" value="NHibernate.Caches.SysCache.SysCacheProvider,NHibernate.Caches.SysCache" /> <add key="relativeExpiration" value="300" /> </config>
Reference the assemblies that implements cache support. For the configuration above:
- NHibernate.Caches.SysCache.dll
Regardless of the cache provider used, NHibernate has three seperate caches that is uses (without counting cache regions, which are user defined). The entity values cache, the collections cache and the query cache. When you enable the second level cache, you enable it for the entities and the collections that choose to be cached. You need to explicitly define which queries you want cached. Note that in general, it is not recommended to enable the query cache (because of stale results from the queries), refer to NHibernate's documenation for the details.
Caching options for entities and collections
Enabling the cache for an entity:
[ActiveRecord( Cache=CacheEnum.ReadOnly )] public class Language : ActiveRecordBase
Enabling the cache for a collection
[HasMany(.... , Cache=CacheEnum.ReadWrite)]
....
[HasAndBelongsToMany(.... , Cache=CacheEnum.ReadOnly)]
....
Again, you should investigate NHibernate documenation for the caching options and their implications
Conclusion
This is all you need to do to enable the cache, NHibernate will automatically fetch items from the second level cache rather then the database when they are present there. This usually drastically reduce the number of queries made to the database, but it also increase the staleness of the data that the application has. Consider the implications carefully before you start using it.