Cache In On the Enterprise Library Caching Block for .NET 2.0

he ability to store items in memory the first time they are requested?whether data objects, pages, or parts of a page?is one of the most important factors in building high-performance, scalable applications. After storing such items in the local cache, you can improve application throughput by returning the cached output in response to subsequent requests rather than recreating them from scratch every time.

Caching has the greatest performance benefit when the information requested demands significant processor time or other resources. In fact, caching is plumbing code that’s too important to create, test, and maintain individually in every .NET application. Recognizing that, Microsoft has created an Application Block known as the “Enterprise Library Caching Block” (or EntLib Caching Block) that provides all the underlying cache plumbing code. This article introduces the EntLib Caching Block and provides examples showing how you can use it to create high performance .NET applications.

Caching Application Block
The EntLib Caching Block lets you incorporate local cache capabilities in your applications. You should consider using the Caching Block in any of the following situations:

  • When your application repetitively accesses relatively static data.
  • When data creation, processing and transport is expensive.
  • When high availability is a major factor.

The Caching Block lets you retrieve, add, and remove data from the cache, providing a fine level of control over the cached data through configuration of expiration and scavenging policies for the cached items. By default, the Caching Block provides three different cache store options, each of which has advantages and disadvantages, as listed below.

  1. In-memory ?This is the default setting, meaning that the application will store cached items in memory. The in-memory cache is non-permanent, but provides the best possible performance compared to other caching stores.
  2. IsolatedStorage?This cache store is permanent, but slightly slower compared to in-memory. For example, you can designate an XML file or an external file as the cache store using this option.
  3. Database (via the Enterprise Library Data Access Block)?This option is similar to the IsolatedStorage option; both are slower than the in-memory option.

The required configuration for the above caching stores is both simple and straightforward; however, using the Database option?involves a few extra steps, because the Caching Block uses the Data Access Block internally to communicate with the database. This article demonstrates how to use the in-memory and database caching store options.

Usecase Scenarios for Caching Block
You can use the Caching Block with a wide variety of .NET application types, including Windows Forms, console applications, Windows services, Enterprise services. In addition, it is possible to use the Caching Block in an ASP.NET Web application or Web service?but you wouldn’t typically take that route because of the rich caching framework already built into ASP.NET 2.0 unless the System.Web.Caching failed to provide some type of necessary caching functionality.

The 2.0 version of the Caching Block 2.0 has been redesigned to take advantage of new .NET 2.0 features. You download it as part of the Enterprise Library for .NET Framework 2.0.

Using the Caching Application Block
After installing the Enterprise Library, you still need to perform some setup steps to use the Caching Block successfully in a project. Follow the steps listed below:

  1. Add a reference to the Microsoft.Practices.EnterpriseLibrary.Common.dll and Microsoft.Practices.EnterpriseLibrary.Caching.dll assemblies to your solution using the “Add Reference” option and navigating to the :Program FilesMicrosoft Enterprise Library January 2006in folder on the drive where you installed the Enterprise Library. If you decide to use the database as a caching store, you also need to add a reference to the Data Access Block (the Microsoft.Practices.EnterpriseLibrary.Caching.Data.dll).
  2. Add the necessary configuration entries to the app.config or web.config file. To this end, you add the element under the root element.
  3.                     
  4. Next, add the element directly under the root element as shown below:
  5.                               
    ?
    Figure 1. Enterprise Library Configuration Tool: The figure shows the in-memory cache configuration settings.

    The preceding settings show how to configure the cache to use an in-memory store by default. While you can add the settings manually, it’s far easier to add them using the Enterprise Library Configuration Tool that ships with Enterprise Library. When viewed through the Enterprise Library Configuration tool the preceding settings look like Figure 1.

  6. Add an “Imports” (or using, in C#) line for the core namespace for the Caching Block, “Microsoft.Practices.EnterpriseLibrary.Caching” to your code.

Now you’re ready to begin writing code that takes advantage of the Caching Block.

Using the CacheFactory Object
Whenever you work with the Caching Block, the first class that you will have to deal with is the CacheFactory class. The CacheFactory class exposes a static method named GetCacheManager() that returns a reference to a specific CacheManager instance. The parameterless overload of GetCacheManager() returns a reference to the default cache manager. To get specific instances of the cache manager, you use the overload that accepts the name of the cache manager. The following code obtains a reference to the default cache manager and stores it in a local variable named employeesCache.

   CacheManager employeesCache =     CacheFactory.GetCacheManager();

After obtaining a reference to the CacheManager instance, you can then easily add, remove, or retrieve items from the caching store.

Here’s an example. Suppose you want to add a simple object to the cache. For the purposes of this article, create a Windows Forms application named CachingBlockExample and add a class named Employee declared as follows:

   [Serializable]   public class Employee   {      int _id;      string _name;      string _address;      public Employee(int id, string name,          string address)      {        _id = id;        _name = name;        _address = address;      }          public int EmployeeID      {         get{return _id; }         set {_id = value;}      }         public string Name      {         get{return _name;}         set{_name = value;}      }         public string Address      {         get{return _address;}         set{_address = value;}      }   }

As you can see, the Employee class simply acts as a placeholder for three public properties: EmployeeID, Name, and Address. The next step is to persist Employee class instances using the Caching Block. To demonstrate this, add a command button named btnAddItem to the default form (named Form1) and modify its Click event as shown below:

   private void btnAddItem_Click(      object sender, EventArgs e)   {      CacheManager employeesCache =          CacheFactory.GetCacheManager();      int id = 1;      string name = "Thiru";      string address = "2644 E Remington";      Employee emp = new Employee(id, name, address);                    employeesCache.Add(      emp.EmployeeID.ToString(), emp,          CacheItemPriority.Normal, null);                           MessageBox.Show("Successfully added");   }

The CacheManager.Add() method lets you add an item associated with a key to the cache. Be careful when using it though?the Add() method removes any existing item with the same key before adding the new item. In other words, the Add() method not only adds, it also replaces items, so if you’re not sure whether a key already exists, check first.

The Add() method takes four parameters: a key, the object to be cached, a CacheItemPriority enumeration, and an object that implements the ICacheItemRefreshAction interface and is responsible for refreshing the cached item. The CacheItemPriority enumeration can be any of the following values: High, Low, None, Normal, and NotRemovable. You can’t change the CacheItemPriority once it’s been set unless you first manually remove and then re-add the item with the changed CacheItemPriority. Note that if you call Add() and an item with that key and a CacheItemPriority of NotRemovable already exists, you’ll get an exception. You’ll see an example of how to leverage the ICacheItemRefreshAction class parameter later in this article.

Retrieve the Cached Employee Object
After adding an object to the cache, you retrieve it from the cache using the CacheManager.GetData() method.

   private void btnRetrieve_Click(      object sender, EventArgs e)   {      CacheManager employeesCache =          CacheFactory.GetCacheManager();      //Retrieve the item from the cache      Employee emp =          (Employee)employeesCache.GetData("1");      MessageBox.Show(emp.Name);               }

Note that the GetData() method takes in the key of the cached item and returns an object that is of type Object, which you must typecast back into an Employee object.

Remove an Employee Object from the Cache
To remove an item from the cache, use the CacheManager.Remove() method and pass in the key of the cached item. The Remove() method does nothing if there is no item in the cache with that key.

   private void btnRemove_Click(      object sender, EventArgs e)   {      CacheManager employeesCache =          CacheFactory.GetCacheManager();      //Remove the item from the cache      employeesCache.Remove("1");      MessageBox.Show("Cached " +         "item successfully removed");   }

If you supply a null value or an empty string as the key parameter to Remove(), the method raises an ArgumentNullException or ArgumentException respectively.

Automatically Refreshing Cached Items
Sometimes you might want to refresh the cache immediately with the latest data whenever the cached item is removed. Additionally, you might want to refresh the cache automatically with the latest data when a cached item has expired or has been explicitly removed from the cache. To accomplish this, perform the steps listed below:

  1. Create a custom class that implements the ICacheItemRefreshAction interface
  2. Implement the Refresh() method with the appropriate code that re-populates the cache with the latest values
  3. Supply the derived class as an argument to the CacheManager.Add() method. This enables the caching framework to automatically invoke the Refresh() method.

Here’s an example custom class that implements the ICacheItemRefreshAction interface.

   using System;   using Microsoft.Practices.      EnterpriseLibrary.Caching;      [Serializable]   public class EmployeeCacheRefreshAction :       ICacheItemRefreshAction   {      public void Refresh(string key,           object expiredValue,           CacheItemRemovedReason removalReason)      {         CacheManager employeesCache =             CacheFactory.GetCacheManager();         int id = 1;         string name = "Thiru";         string address ="2644 E Remington";         Employee emp = new Employee(id,             name, address);         employeesCache.Add(         emp.EmployeeID.ToString(), emp,          CacheItemPriority.Normal, null);      }   }   

In the preceding code, the Refresh() method obtains a reference to the CacheManager and then refreshes the cache with the latest employee data.

After creating the EmployeeCacheRefreshAction class, you can pass an instance of the class to the CacheManager.Add() method as shown below.

   employeesCache.Add(      emp.EmployeeID.ToString(), emp,       CacheItemPriority.Normal,      new EmployeeCacheRefreshAction());

After doing that, any removal of the Employee object from the cache triggers the EmployeeCacheRefreshAction.Refresh() method.

Using a Database Cache Store
Using the in-memory store you’ve seen so far as the caching store is efficient, but it isn’t permanent. To switch from an in-memory cache to a database cache, follow these steps:

  • Execute the SQL script in the file CreateCachingDatabase.sql, which you can find at :Program FilesMicrosoft Enterprise Library January 2006srcCachingDatabaseScripts
  • Modify the app.config file to use the appropriate caching providers.
  • Add a reference to the Microsoft.Practices.EnterpriseLibrary.Caching.Data.dll assembly to your solution

Listing 1 shows how the modified app.config file might look:

Notice that the app.config file in Listing 1 also adds the Data Access Block settings. This is required, because the Caching Block leverages the Data Access Block internally to persist and retrieve data from the database. Conveniently, after modifying the app.config file with the settings shown in Listing 1 in place, the code to add, remove, and retrieve items from the database cache doesn’t need to change at all; in other words, you can change the backing cache store without modifying your code.

As you have seen from this article, the EntLib Caching Block obviates the need to write repetitive caching plumbing code by providing a set of highly reusable classes for adding, retrieving, and removing items from the cache. By using the Caching Block classes, you can reduce errors, bugs, and typos in your application and focus more attention on the core business logic of the application to achieve increased productivity.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: