This is a a second article on the topic of the Microsoft Enterprise Library. If you have not read the previous article titled Microsoft Enterprise Library: Data Access Application Block, I recommend you do so.
Introduction to the Caching Application Block
The Enterprise Library Caching Application Block lets developers incorporate a local cache in their applications. It supports both an in-memory cache and, optionally, a backing store that can either be the database store or isolated storage. The Caching Application Block can be used without modification; it provides all the functionality needed to retrieve, add, and remove cached data. Configurable expiration and scavenging policies are also part of the block.
If you have been working with caching outside the Enterprise Library, I believe you will find this application block extremely powerful and easy to use. If you have not taken on the subject of caching before, I believe you also will find this easy to pick up and ultimately boost the performance of your applications. The Enterprise Library Caching Application Block includes the following features:
- You can use the graphical Enterprise Library configuration tools to manage configuration settings.
- You can configure a persistent storage location, using either isolated storage or the Enterprise Library Data Access Application Block, whose state is synchronized with the in-memory cache.
- Administrators can manage the configuration using Group Policy tools.
- You can extend the block by creating custom expiration policies and storage locations.
- You are assured that the block performs in a thread-safe manner.
Cache Manager
The cache manager serves the role of managing the cache store exactly as it sounds. It is entirely possible to have multiple cache managers to suit you business requirements. When configuring the cache manager you also have choices when it comes to the backing stores. For example, if you wish to use a database to persist the cache you can do so, but for the purpose of this article I will demonstrate the out of the box configuration which is the server’s memory.
Much like the potential vulnerabilities surrounding the Data Access Block in terms of SQL Injection, the Caching Application Block also has risk that you must understand. For example, do not store sensitive data in the cache and if you must do so, then use encryption.
Once you have the defined your cache manager settings, you will see similar code withing your web.config:
<configSections> <section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching. Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" /> </configSections> <cachingConfiguration defaultCacheManager="RadDev Cache Manager">
Design and Implementation
Turning our attention to the web project, the first step is to add the appropriate references. Add a reference to the Caching Application Block assembly. In Microsoft Visual Studio, right-click your project node in Solution Explorer, and then click Add Reference. Click the Browse tab and find the location of the Microsoft.Practices.EnterpriseLibrary.Caching.dll assembly. Select the assembly, and then click OK to add the reference.
Now that the references are in place, we need the using statements.
//Enterprise Library using Microsoft.Practices.EnterpriseLibrary.Caching; using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
Now the fun begins. We will query the database and after this first round trip we will cache the data. By caching the data the next call to the database essentially does not occur. Back in your webform add a GridView.
<asp:GridView ID="GridViewContactsNoCache" runat="server"> </asp:GridView>
Now that we have the GridView established it is time to wire up the necessary code to communicate with the database and then display this data to the end user.
First step here is to create your reference to the cache manager.
ICacheManager cache = EnterpriseLibraryContainer.Current.GetInstance<ICacheManager>();
Depending upon your application’s design you can add a object to cache in the scenario that works best for you. Here I am using a Generic List to create an object type of Contact. I will not go into the details of the List nor the Contact Class, but I will share the code so you can follow the thought process.
SQL Statement
private const string sqlOne = "SELECT FirstName," + " MiddleName, LastName FROM Person.Contact WHERE (LastName =" + " N'adams') AND (FirstName LIKE N'r%') ORDER BY LastName";
Page Load Event
Inside the page load you will notice an if/else statement. Here is where we check if the Contacts object is in cache and if so, we bypass the database round trip and bind the GridView to this cache object.
protected void Page_Load(object sender, EventArgs e)
{
if (cache.Contains("ContactsCachKey"))
{
GridViewContactsNoCache.DataSource = cache.GetData("ContactsCachKey");
}
else
{
GridViewContactsNoCache.DataSource = GetContacts();
}
GridViewContactsNoCache.DataBind();
// How many object are in cache?
LabelCacheObjects.Text = string.Format("The Cache Manager contains {0} objects.",
cache.Count.ToString());
}
Get the Contacts
In this method you will see the use of the Generic List and immediately before exiting the method I am making another method call to populate the Contacts to cache.
private List<Contact> GetContacts()
{
using (IDataReader rdr = db.ExecuteReader(CommandType.Text, sqlOne))
{
lstContact = new List<Contact>();
while (rdr.Read())
{
contact = new Contact();
contact.FirstName = rdr.GetString(0);
contact.MiddleName = rdr.GetString(1);
contact.LastName = rdr.GetString(2);
lstContact.Add(contact);
}
}
PopulateCacheManager(lstContact);
return lstContact;
}
private void PopulateCacheManager(List<Contact> lstContact)
{
cache.Add("ContactsCachKey", lstContact);
}
The Result

What If The Data Changes
Of course when one displays data, typically the counterpart is to also update the data. You will be pleased to know that in one line of code you can destroy the Contacts cached object and upon the next execution of displaying the data, the process starts all over. Assume for a moment that that Update button click has processed a database transaction.
protected void ButtonUpdate_Click(object sender, EventArgs e)
{
cache.Remove("ContactsCachKey"); //here we remove the Contacts cache object
}
Conclusion
As you can see, using the Caching Application Block component of the Enterprise Library is not complex. Of course, this article has just begun to scratch the surface in the hopes that your interest is perked.
Examples Via MSDN
The following examples are from the Enterprise Library 5.0, Chapter 5 – A Cache Advance for Your Applications.
Proactive Cache Loading
The example, Load the cache proactively on application startup, provides a simple demonstration of proactive cache loading. In the startup code of your application you add code to load the cache with the items your application will require. The example creates a list of Product items, and then iterates through the list calling the Add method of the cache manager for each one. You would, of course, fetch the items to cache from the location (such as a database) appropriate for your own application. It may be that the items are available as a list, or—for example—by iterating through the rows in a DataSet or a DataReader.
// Create a list of products - may come from a database or other repository
List<Product> products = new List<Product>();
products.Add(new Product(42, "Exciting Thing",
"Something that will change your view of life."));
products.Add(new Product(79, "Useful Thing",
"Something that is useful for everything."));
products.Add(new Product(412, "Fun Thing",
"Something that will keep the grandchildren quiet."));
// Iterate the list loading each one into the cache
for (int i = 0; i < products.Count; i++)
{
theCache.Add(DemoCacheKeys[i], products[i]);
}
Reactive Cache Loading
Reactive cache loading simply means that you check if an item is in the cache when you actually need it, and—if not—fetch it and then cache it for future use. You may decide at this point to fetch several items if the one you want is not in the cache. For example, you may decide to load the complete product list the first time that a price lookup determines that the products are not in the cache.
The example, Load the cache reactively on demand, demonstrates the general pattern for reactive cache loading. After displaying the contents of the cache (to show that it is, in fact, empty) the code attempts to retrieve a cached instance of the Product class. Notice that this is a two-step process in that you must check that the returned value is not null. As we explained in the section “What’s In My Cache?” earlier in this chapter, the Contains method may return true if the item has recently expired or been removed.
If the item is in the cache, the code displays the values of its properties. If it is not in the cache, the code executes a routine to load the cache with all of the products. This routine is the same as you saw in the previous example of loading the cache proactively.
Console.WriteLine("Getting an item from the cache...");
Product theItem = (Product)defaultCache.GetData(DemoCacheKeys[1]);
// You could test for the item in the cache using CacheManager.Contains(key)
// method, but you still must check if the retrieved item is null even
// if the Contains method indicates that the item is in the cache:
if (null != theItem)
{
Console.WriteLine("Cached item values are: ID = {0}, Name = '{1}', "
+ "Description = {2}", theItem.ID, theItem.Name,
theItem.Description);
}
else
{
Console.WriteLine("The item could not be obtained from the cache.");
// Item not found, so reactively load the cache
LoadCacheWithProductList(defaultCache);
Console.WriteLine("Loaded the cache with the list of products.");
ShowCacheContents(defaultCache);
}



Recent Comments