Configuring the cache

Caching frequently used, rarely updated data can greatly improve the performance of websites and other high traffic applications. In this recipe, we'll configure NHibernate's cache, just as we would for a typical public facing website.

Getting ready

  1. Complete the Configuring NHibernate with App.config recipe from Chapter 1.
  2. Download the NHibernate Caches binary files from SourceForge at http://sourceforge.net/projects/nhcontrib/files/.
  3. Extract NHibernate.Caches.SysCache.dll to your solution's Lib folder.

How to do it...

  1. Add a reference to NHibernate.Caches.SysCache.dll.
  2. Open the App.config file.
  3. In the configSections element, declare a section for the cache configuration:
    <section name="syscache"
        type="NHibernate.Caches.SysCache.SysCacheSectionHandler, 
              NHibernate.Caches.SysCache" />
  4. Add the following three properties to the hibernate-configuration section.
    <property name="cache.provider_class">
      NHibernate.Caches.SysCache.SysCacheProvider, 
      NHibernate.Caches.SysCache
    </property>
    
    <property name="cache.use_second_level_cache">
      true
    </property>
    
    <property name="cache.use_query_cache">
      true
    </property>
  5. After the mapping element, add the following cache elements:
    <class-cache class="Eg.Core.Product, Eg.Core" 
         region="hourly" usage="read-only"/>
    
    <class-cache class="Eg.Core.ActorRole, Eg.Core" 
         region="hourly" usage="read-only"/>
    
    <collection-cache collection="Eg.Core.Movie.Actors" 
         region="hourly" usage="read-only "/>
  6. After the hibernate configuration section, add the syscache section declared in the first step:
    <syscache>
      <cache region="hourly" expiration="60" priority="3" />
    </syscache>
  7. Build and run your application.

How it works...

The cache.provider_class configuration property defines the cache provider to use. In this case, we're using syscache, NHibernate's wrapper for ASP.NET's System.Web.Caching.Cache.

The cache.use_second_level_cache enables the second-level cache. If the second-level cache is enabled, setting cache.use_query_cache will allow query results to be cached.

Caching must still be set up on a per-class hierarchy, per-collection, and per-query basis. That is, you must also set up caching for each specific item to be cached. In this recipe, we've set up caching for the Product entity class, which, because they're in the same class hierarchy, implicitly sets up caching for Book and Movie with the same settings. In addition, we've set up caching for our ActorRole entity class. Finally, because caching for collections is configured separately from entities, we set up caching for the Movie's Actors collection.

We've set up each of these to use a region of the cache named hourly. A cache region separates the cached data and defines a set of rules governing when that data will expire. In this case, our hourly region is set to remove an item from the cache after 60 minutes or under stress, such as low memory. priority can be set to a value from 1 to 5, with 1 being the lowest priority, and thus the first to be removed from the cache.

The cache concurrency strategy for each item, set with the usage attribute, defines how an object's cache entry may be updated. In this recipe, we've set all of our product data to read-only. Our public-facing website only displays our products. It doesn't change them. In other scenarios, it may be appropriate to use read-write or, when concurrency isn't a concern, nonstrict-read-write.

Tip

Caching is only meant to improve the performance of a properly designed NHibernate application. Your application shouldn't depend on the cache to function properly. Before adding caching, you should correct poorly performing queries and issues like SELECT N+1. This will usually give a significant performance boost, eliminating the need for caching and its added complexity.

There's more...

NHibernate allows us to configure a cache with the same scope as the session factory. Logically, this cache is divided into three parts.

Entity cache

The entity cache stores persistent objects or the values of persistent objects. These objects are stored as a dictionary of POIDs to arrays of values, as shown in the following diagram:

Entity cache

Notice in the previous image that the Movie.Actors collection has a cache entry of its own. Also notice that in this entry, we're storing the POIDs of the ActorRole objects, not the ActorRole data. There is no data duplication in the cache. From the cached data shown in the diagram, we can easily rehydrate the entire object graph for the movie without the chance of any inconsistent results.

Query cache

In addition to caching entities, NHibernate can also cache query results. In the cache, each query is associated with an array of POIDs for the entities of the query returns, similar to the way our movie actor collection is stored in the previous image. The entity data is stored in the entity cache. Again, this eliminates the chance of inconsistent results.

Update timestamp cache

The third part of the cache stores a last-updated timestamp for each table. When data is first placed in the cache, the timestamp is set to a value in the future, ensuring the cache will never return uncommitted data from a pending transaction. Once the transaction is committed, the timestamp is set back to the present, allowing that data to be read from the cache.

The rules

There are some basic requirements when using the cache:

  • Always explicitly begin a transaction before any database interaction, even when reading data from the database. This is a required practice with NHibernate in general, but it is especially important for interacting with the cache. Without an explicit transaction, caching is bypassed.
  • When opening a session, don't provide your own database connection. This also affects caching. Instead, implement your own IConnectionProvider, and set the connection.provider configuration property as in the Using dynamic connection strings recipe in Chapter 7.

See also

  • Configuring NHibernate with App.config
  • Using dynamic connection strings
  • Configuring the cache with code
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.220.83