1. Introduction

In this article, I explain how NHibernate 2nd level cache is implemented. As an Object Relational Mapper (ORM) when NHibernate is used often we see developers try to improve performance using NHibernate caching feature. In this article I focus on this area where 2nd level cache plays rule for better performance. Second level cache will help to overcome 1st level cache limitations. Anyone who are also interested to know how 2nd level caching can be implemented in any project, this article is for them too .

2. Prerequisite

NHibernate basics

1st level caching

3. Background

Entity level caching is a very important technique and it improves performance of application. Occasionally we introduce caching layer in n-layer architecture which exists just before data access layer. The main responsibility of this layer is cache business and supply business entities to the business layer from its cache when business layer demands.

When anyone use NHibernate and its 2nd level caching feature then further it will not be needed to cache entities in other layers. NHibernate provides various caching and its expiration policy. I try to explain it in a very easy way so that any one can easily use it in their application.

4. Prerequisite Components

If anyone wants to use NHibernet in his applications, then few components must be needed and he should add as a reference of those components to his projects. Components are:

NHibernate

Lesi.Collections

If you prefer fluent configuration (I prefer fluent mapping configuration over xml mapping configuration), then you can take reference of another:

FluentNHibernate

These are the core components of NHibernate.

5. 2nd Level Cache Providers

If I want to use 2nd level cache feature, at first I need to add at least one 2nd level cache provider reference to my project.

Many cache providers are exists in market. Few popular providers are:

MemCache

Velocity

SysCache

SysCache2

Hash Table

I prefer SysCache2 because it supports database change notification. If your applications need distributed cache, then you can check with Velocity. For adding SysCache2 component reference to my project, I prefer NuGet package cmd lets. You can use:

Note that it will not add reference of FluentNHibernate component. You manually need to add that.

6. Configuration

After adding component reference you need to configure your

Database and

Application

so that it can work perfectly.

6.1. Database Configuration

If you want to take database change notification service then you need to setup SQL Server 2005 or higher version (I found various online sources there said SqlServer 2000 also supports it, but never tried that). Next, we need to enable SQL Server Service Broker feature. TSQL statement is:

ALTER DATABASE <databasename> SET ENABLE_BROKER;

Note that, you can enable service broker feature in a database for only once. We can also disable service broker feature at any time. TSQL statement is:

You can create a single batch (.bat) file with all the necessary commands listed above. It will make your life more easier.

6.2. Application Configuration

You may think that NHibernate 2nd level cache is worked with only in web context. But it is not true. You can easily use that feature in your Console, Windows Service application, Windows Application too.

In your configuration file (if web application then it will be web.config, if other then web then it will be app.config) you need to register syscache2section inside <configSections> node:

then you need to register sqlCacheDependencyinside <system.web> node. If you use App.config, then you need to add <system.web> node under <configuration> node and also add a reference to the System.Web component. SqlCacheDependencyobject actually resides in this component and it is .NET Framework component. For that reason it will work in your application that does not have any web context.

A. Actually syscache2 expires its cache based on database change notification (Well, not always but, only when you configure the "regions" that way). SqlCacheDependency object is actually manage that and SysCache2 use it.

One important attribute is pollTime (in milliseconds). The value of pollTime indicate time interval when it visit database periodically to check if there are any changes.

SysCache2 region registers in the web/app config. <syscache2> node will be registered under <configuration> node.

You can see that there is a node "cacheRegion" named “tableDependency”. CacheRegion is actually an independent cache expiration policy. From our Entity Mapping configuration, we can refer to that policy. databaseEntryName attribute of <tables> node refer to <add name=db2> under <databases> & <sqlDependency> node. This databaseEntryName attribute sometimes creates confusion and that is, what will be its value. So carefully, we should set that value.

Another <cacheRegion> is registered for cache expiration on certain time:

The above region reference cache will be stored in cache in 5 seconds. After that period, it will automatically expire.

7. NHibernate Session

In NHibernate, we need to create a SessionFactory class. Using that class we can open a new session and start communicating with database. Create SessionFactory object is costly and for that reason we should create it as a singleton session. That means per application context it will create ony one timme. SessionFactory object creation code sample:

In the above code, the DeveloperMap class's constructor, first line declares that it needs to support Cache and configure its cache expiration policy based on Region declaration. There are many types of Cache usage pattern that are supported, for example ReadOnly, NonStrictReadWrite, etc. If you search on the web, you can find more information regarding that.

9. Conclusion

NHibernate 2nd level caching is a very unique feature and it has capability to improve application performance. Point to be noted that it is a caching Technic similar to other caching. Before you apply it must carefully think and plan against entities which you need to support 2nd level cache and define its expiration policy. If you make a mistake to choose proper entities to cache and its best expiration policy, then it will not provide any benefits, moreover this may create many bugs. So before planning/configuring your entities for taking advantage from 2nd level cache, spend time to rethink and revise and verify and share it to your team members so that no error found in your plan/configuration/entity selection for cache.

Comments and Discussions

I have just looked into this and as far as I can see there is no need to enable Servce Broker in this instance. For table dependency configuration polling is used and the stored procedure, AspNet_SqlCachePollingStoredProcedure, is called every 1000 ms as configured as pollTime. So instead of Query Change Notification where the database tells the application that there are new changes the applications polls the database.