Home

Castle Stronghold

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.

Quick Note

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 caching documenation.

Warning

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.

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:

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.

Google
Search WWW Search castleproject.org