NHibernate cache system. Part 1 | Raffaeu’s blog

In this series of articles I will try to explain you how NHibernate cache system works and how it should be used in order to get the best performance/configuration from this product.

  • Introduction
    • Architecture
    • Cache Level 1 mechanism
    • Load and Get, what’s the difference
    • Session maintenance: Evict, Flush and Clear
  • 2nd Level Cache
    • Architecture
    • Configuration
    • Cache by mapping
    • Cache by query
    • Final advice
  • Cache providers (most known)

NHibernate Cache architecture

NHibernate has an internal cache architecture that I will define absolutely well done. On an architectural point of view, it is designed for the enterprise and it is 100% configurable. Consider that it allows you to create also your custom cache provider!

The following picture show the cache architecture overview of NHibernate (actually the version I am talking about is the 3.2 GA).

The cache system is composed by two levels, the cache of level 1 that usually it is configured by default if you are working with the ISession object, and the cache of level 2 that by default is disabled.

The cache of level 1 is provided by the ISession data context and it is maintained by the lifecycle of the ISession object, this means that as soon as you destroy (dispose) an ISession object, also the cache of level 1 will be destroyed and all the corresponding objects will be detached from the ISession. This cache system works on a per transaction basis and it is designed to reduce the number of database calls during the lifecycle of an ISession. As an example, you should use this cache if you have the need to access and modify an object in a transaction, multiple times.

The cache of level 2 is provided by the ISessionFactory component and it is shared across all the session created using the same factory. Its lifecycle correspond to the lifecycle of the session factory and it provides a more powerful but also dangerous set of features. It allows you to keep objects in cache across multiple transactions and sessions; the objects are available everywhere and not only on the client that is using a specific ISession.

Cache Level 1 mechanism

As soon as you start to create a new ISession (not an IStatelessSession!!) NHibernate starts to holds in memory, using a specific mechanism, all the objects that are involved with the current session. The methods used by NHibernate to load the data into the cache are two: Get<T>(id) and Load<T>(id). This means that if you try to load one or more entities using: LinQ, HQL, ICriteria … NHibernate will not put them into the cache of level 1.

Another way to put an object into the lvl1 cache is to use persistence methods like Save, Delete, Update and SaveOrUpdate.

As you can see from the previous picture, the ISession object is able to contains two different categories of entities, the one that we define “loaded” using Get or Load and the one that we define “dirty”, which means that they were somehow modified and associated with a session.

Load and Get, what’s the difference?

A major confusion I personally noticed while working with NHibernate is the not correct usage of the two methods Get and Load so let’s see for a moment how they work and when they should or should not be used.

Get

Load

Fetch method

Retrieve the entire entity in one SELECT statement and puts the entity in the cache.

Retrieve only the ID of the entity and returns a non fetched proxy instance of the entity. As soon as you “hit” a property, the entity is loaded.

How it loads

It verifies if the entity is in the cache, otherwise it tries to execute a SELECT

It verifies if the entity is in the cache, otherwise it tries to execute a SELECT

Not Available

If the entity does not exist, it returns NULL

If the entity does not exist, it THROW an exception

I personally prefer Get because it returns NULL instead of throwing a nasty exception, but this is a personal choice; while some of you may prefer to use Load because you want to avoid a database call until is really needed.

Below I wrote a couple of very simple tests to show you how the Get and Load methods work across the same ISession.

Get<T>()

Leave a comment

Your email address will not be published. Required fields are marked *