Implement Caching to Give Your .NET Applications a Performance Boost

The most dramatic way to improve the performance of a database-driven application is through caching. Retrieving data from a database is one of the slowest operations that a Web application performs. If it caches the database data in memory, however, it avoids accessing the database with every request—which dramatically increases its performance.

To implement caching, you must create common plumbing code that provides the basic functionality. Instead of creating this code in every project, wouldn't it be great to encapsulate this common plumbing code in a reusable block and reuse it in different projects? Well, that is exactly what the Enterprise Library (EntLib) caching block provides. This article introduces the EntLib caching block and demonstrates how to leverage it from a .NET application.

How the EntLib Caching Block Works

The EntLib caching block enables you to incorporate a local cache in your applications. It is ready to use without any modification; it provides all the functionality you need to retrieve, add, and remove cached data. The caching block also enables you to configure expiration and scavenging policies for the cached items.

By default, the caching block provides the following three types of caching mechanisms:

  • In memory (Null): The in-memory cache stores the cached items in memory. It's non-permanent, but fast.
  • IsolatedStorage: This cache store is permanent but slightly slower than in-memory. For example, it could be an XML file or an external file.
  • Database: As with IsolatedStorage, the database option also is slower. It requires the use of the EntLib data access block as well.

The caching block is suitable for any of the following situations:

  • Static data needs to be repeatedly accessed
  • Creation, processing, and transportation of data is expensive
  • High availability is a major factor

You can use the caching block with any of the following application types:

  • Windows Forms
  • Console
  • Windows Service
  • Enterprise Services
  • ASP.NET Web application or Web service if you need features that are not included in the ASP.NET cache

The CacheManager class is the primary interface between the application and the rest of the caching block. It handles operations related to caching by creating a Cache object, which is an in-memory representation of the backing store. You also can configure this class to store data either only in memory or both in memory and in persistent storage.

To create an instance of a CacheManager object, you need to use the CacheFactory class, which in turn uses the CacheManagerFactory class. The CacheManagerFactory class creates all the internal classes needed to implement a CacheManager object.

Installation

Before using the EntLib caching block, take the following steps to get it installed and configured in your local machine:

  1. Download the EntLib.
  2. Navigate the Start menu to All Programs->Microsoft patterns and practices->Enterprise Library->Build Enterprise Library. This will build all the EntLib blocks including the caching block.
  3. Once the assembly has been built, you can add references to the caching block assembly and the required dependant assemblies (Microsoft.Practices.EnterpriseLibrary.Caching.dll, Microsoft.Practices.EnterpriseLibrary.Common.dll, and Microsoft.Practices.EnterpriseLibrary.Configuration.dll) from <DriveName>:\Program Files\Microsoft Enterprise Library June 2005\bin.
  4. Note: A reference to the configuration block assembly is required because the caching block has a dependency on the configuration for reading configuration settings from the configuration file.
  5. Create the necessary configuration files using the Enterprise Library Configuration Tool.
  6. Once the assemblies are referenced, import the required namespaces. To leverage the EntLib caching block, add the following imports statements to your code:
  7. using Microsoft.Practices.EnterpriseLibrary.Caching;
    using Microsoft.Practices.EnterpriseLibrary.Caching.
                    Expirations;
    

Now, you're ready to begin. Start by creating the configuration file through the configuration utility.

Creating Configuration Files

The Enterprise Library Configuration Tool helps create the necessary configuration files so that the caching block can retrieve the configuration settings from a set of configuration files. To create the configuration file, bring up the Enterprise Library Configuration Tool and select File->New Application from the menu. Right-click on the newly created application (named Application1) and select New->Caching Application Block from the context menu and specify the configuration settings. Figure 1 shows the configuration settings that the examples in this article use.

Figure 1: Configuration Settings for Examples

When you save the settings shown in Figure 1, the tool will create two files: one with the name that you entered in the File Save As prompt (specify the name as app.config file for the purposes of this example) and the other one with the name cachingConfiguration.config. The cachingConfiguration.config file is the one that contains the actual cache-related configuration settings.

Now that you have a general understanding of the EntLib caching block, let's look at some examples.

Implement Caching to Give Your .NET Applications a Performance Boost

Adding an Item to the Cache

To illustrate the advantages of the caching block, take a look at some sample code that creates an object named NameValuePair and adds that to the cache. First, create a new Visual C# Windows Form application using Visual Studio 2005.

Note: If you use Visual Studio 2003, the code will work the same.

Once you've created the project, add the app.config created through the Enterprise Library Configuration Tool to the root of the project. Also, add the cacheConfiguration.config file to the bin/debug directory that is under the project root directory. Once the project is created, add a reference to the caching block namespaces as follows:

using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;

Add a private variable of type CacheManager object as shown below:

private CacheManager cacheManager;

The cacheManager variable must be able to reference a valid CacheManager object. For that, add the following line of code to the form constructor:

// Use the default cache manager for the cache operations
cacheManager = CacheFactory.GetCacheManager();

The above code returns a reference to the CacheManager object through the GetCacheManager() method of the CacheFactory class. The parameter-less GetCacheManager() method returns a reference to the default cache manager, which in this case is in memory. You also can return a reference to a specific predefined cache manager by specifying the name of the cache manager class. This is defined in the following cacheConfiguration.config file:

<cacheManagers>
   <cacheManager name="Default Cache Manager"
      expirationPollFrequencyInSeconds="60"
      maximumElementsInCacheBeforeScavenging="1000"
      numberToRemoveWhenScavenging="10">
      <cacheStorage xsi:type="CustomCacheStorageData"
         name="Null Storage"
         type="Microsoft.Practices.EnterpriseLibrary.Caching.
         BackingStoreImplementations.NullBackingStore,
         Microsoft.Practices.EnterpriseLibrary.Caching">
         <extensions />
      </cacheStorage>
   </cacheManager>
       --------
       --------
       --------
</cacheManagers>

Now, open up the Windows Form and add a command button named btnAddItem. Modify its Click event to look as follows:

private void btnAddItem_Click(object sender, EventArgs e)
{
   NameValuePair obj = new NameValuePair();
   obj.Name ="First Item";
   obj.Value ="1";
   cacheManager.Add("1", obj,CacheItemPriority.High, new
      CustomCacheRefreshAction(),
      new AbsoluteTime(DateTime.Now.AddHours(24)));
   MessageBox.Show("Item added successfully");
}

The NameValuePair class in the above example is defined as follows:

[Serializable]
public class NameValuePair
{
   string _name;
   string _value;

   public string Name
   {
      get
      {
         return _name;
      }
      set
      {
         _name = value;
      }
   }

   public string Value
   {
      get
      {
         return _value;
      }
      set
      {
         _value = value;
      }
   }
}

In the Click event of the btnAddItem button, start by creating an instance of the NameValuePair object and setting its values appropriately:

NameValuePair obj = new NameValuePair();
obj.Name ="First Item";
obj.Value ="1";

After that, add the NameValuePair object to the cache by invoking the Add() method of the CacheManager object:

cacheManager.Add("1", obj,CacheItemPriority.High, new
   CustomCacheRefreshAction(),
   new AbsoluteTime(DateTime.Now.AddHours(24)));

The Add() method accepts the following parameters:

  • A key that uniquely identifies the stored item in the cache
  • Enumeration that specifies the priority of the item stored in the cache
  • A custom class that implements the ICacheItemRefreshAction interface (The Refresh() method of the ICacheItemRefreshAction interface allows you to execute custom code whenever the item has been removed from the cache.)
  • Time at which the cached item needs to expire

For the purposes of this example, the CustomCacheRefreshAction class contains just the declaration of the Refresh() method:

[Serializable]
public class CustomCacheRefreshAction : ICacheItemRefreshAction
{
   public void Refresh(string key, object expiredValue,
                       CacheItemRemovedReason removalReason)
   {
      // Item has been removed from cache. Perform desired actions
      // here, based upon the removal reason (for example,
      // refresh the cache with the item).
   }
}

Finally, display a message box indicating that the item is added successfully:

MessageBox.Show("Item added successfully");

If you run the application and click the command button, you should see a message box that says "Item added successfully."

Retrieving an Item from the Cache

Now that you have successfully added an item to the cache, look at the code required to retrieve that item from the cache. Add a command button named btnRetrieve to the form and modify its click event to look as follows:

private void btnRetrieve_Click(object sender, EventArgs e)
{
   NameValuePair obj = (NameValuePair)cacheManager.GetData("1");
   if (obj != null)
      MessageBox.Show("Name: " + obj.Name + ", Value = "
                               + obj.Value);
   else
      MessageBox.Show("Item not found in the cache");
}

Retrieving an item from the cache requires the use of the GetData() method of the CacheManager object. To this method, supply the key of the cached item. It returns an object of type object, which you then can type cast into a NameValuePair object. Then, you simply display the values contained in the NameValuePair object through the message box, if the object returned by the CacheManager is a valid object. If you run the application, you can get output similar to Figure 2.

Figure 2: Output from Application Retrieving an Item from Cache

Removing an Item from the Cache

Once you have an item in the cache, you might want to remove it. As with retrieving an item from the cache, removing an item also requires you to supply the key of the cached item as an argument. The CacheManager object exposes the Remove() method for this purpose. Here is the code required to remove an item from the cache:

private void btnRemove_Click(object sender, EventArgs e)
{
   cacheManager.Remove("1");
   MessageBox.Show("Item removed from the cache");
}

To the Remove() method, you supply the key of the cached item.

Flushing the Cache

The last use case in this example is flushing out the cache. You might need to flush out the cache before you shut down your application. To this end, the CacheManager exposes a method named Flush() that you can call to flush the cache:

private void btnFlush_Click(object sender, EventArgs e)
{
   cacheManager.Flush();
   MessageBox.Show("Item flushed from the cache");
}

As expected, the Flush() method does not take in any parameters. It simply clears all the items from the cache.

Caching: The Performance Booster

Caching has a dramatic impact on the performance of database-driven .NET applications. You can use caching to store data that an application consumes frequently; you also can use it to store data that is expensive to create, obtain, or transform. The EntLib caching block enables you to implement caching functionality in your applications easily. By using the caching block, you also can eliminate errors, bugs, and typos in your application by reusing proven and tested code.

About the Author

Thiru Thangarathinam has many years of experience in architecting, designing, developing, and implementing applications using object-oriented application development methodologies. His certifications include MCAD for .NET, MCSD, and MCP. Thiru is an expert in ASP.NET, .NET Framework, Visual C# .NET, Visual Basic .NET, ADO.NET, XML Web services, and .NET remoting. Thiru also has authored numerous books and articles. Contact him at thiruthangarathinam@yahoo.com.



Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

  • Do you know where your data is? Consumer cloud-based file sharing services store your sensitive company data on servers outside of your control, outside of your policy and regulatory guidelines – maybe even outside your country – and not managed by you. The potential for data leakage, security breaches, and harm to your business is enormous. Download this white paper to learn about file sync and share alternatives that allow you to manage and protect your sensitive data while integrating and …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds