Microsoft ASP.NET 3.5 : Caching Application Data (part 1) - The Cache Class

1/12/2013 3:18:19 AM

Preserved for backward compatibility with classic ASP applications, the Application intrinsic object presents itself as a global container of data with an indexer property and a user-callable locking mechanism. The Cache object is a smarter and thread-safe container that can automatically remove unused items, support various forms of dependencies, and optionally provide removal callbacks and priorities.

The Application object is maintained for backward compatibility with legacy applications; new ASP.NET applications should use the Cache object.

1. The Cache Class

The Cache class is exposed by the System.Web.Caching namespace and is a new entry in the set of tools that provide state management in ASP.NET. The Cache class works like an applicationwide repository for data and objects, but this is the only aspect that it has in common with the HttpApplicationState class, as we’ll see in a moment.

An instance of the Cache class is created on a per-AppDomain basis and remains valid until that AppDomain is up and running. The current instance of the application’s ASP.NET cache is returned by the Cache property of the HttpContext object or the Cache property of the Page object.

Cache and Other State Objects

In spite of their common goal—to serve as a global data repository for ASP.NET applications—Cache and HttpApplicationState classes are quite different. Cache is a thread-safe object and does not require you to explicitly lock and unlock before access. All critical sections in the internal code are adequately protected using synchronization constructs. Another key difference with the HttpApplicationState class is that data stored in Cache doesn’t necessarily live as long as the application does. The Cache object lets you associate a duration as well as a priority with any of the items you store.

Any cached item can be configured to expire after a specified number of seconds, freeing up some memory. By setting a priority on items, you help the Cache object select which items can be safely disposed of in case of memory shortage. Items can be associated with various types of dependencies, such as the timestamp of one or more files and directories, changes on other cached items, database table changes, and external events. When something happens to break the link, the cached item is invalidated and is no longer accessible by the application.

Both Cache and HttpApplicationState are globally visible classes and span all active sessions. However, neither works in a Web farm or Web garden scenario; in general, they don’t work outside the current AppDomain.


When more than one AppDomain is involved (for example, in a Web farm), presumably all AppDomains would contain the same cached data, assuming that the cached information is not dynamic. Unlike with session state, this isn’t as troubling because the assumption is that applicationwide static values can be read upon initialization and cache timeout. If the cached information is dynamic, that’s a different story. In that case, you should consider a global cross-machine container, as we’ll discuss shortly.

The Cache object is unique in its capability to automatically scavenge the memory and get rid of unused items. Aside from that, it provides the same dictionary-based and familiar programming interface as Application and Session. Unlike Session, the Cache class does not store data on a per-user basis. Furthermore, when the session state is managed in-process, all currently running sessions are stored as distinct items in the ASP.NET Cache.


If you’re looking for a global repository object that, like Session, works across a Web farm or Web garden architecture, you might become frustrated. No such object exists in the .NET Framework. To build a cross-machine container, you need to resort to a shared and remote resource, such as an external service or perhaps an installation of Microsoft SQL Server or another database. This means that each access to data will require serialization and is subject to network latency. In general, this scheme is complex enough to invalidate most of the advantages you get from data caching. As far as caching is involved, the tradeoff to evaluate is accessing ready-made data versus running the query to fetch a fresh copy of desired data. ASP.NET provides an effective infrastructure for caching data locally because that is what you need most of the time. Adding to the infrastructure to cover farms is up to you.

Properties of the Cache Class

The Cache class provides a couple of properties and public fields. The properties let you count and access the various items. The public fields are internal constants used to configure the expiration policy of the cache items. Table 1 lists and describes them all.

Table 1. Cache Class Properties and Public Fields
CountGets the number of items stored in the cache
ItemAn indexer property that provides access to the cache item identified by the specified key
NoAbsoluteExpirationA static constant that indicates a given item will never expire
NoSlidingExpirationA static constant that indicates sliding expiration is disabled for a given item

The NoAbsoluteExpiration field is of the DateTime type and is set to the DateTime.MaxValue date—that is, the largest possible date defined in the .NET Framework. The NoSlidingExpiration field is of the TimeSpan type and is set to TimeSpan.Zero, meaning that sliding expiration is disabled. We’ll say more about sliding expiration shortly.

The Item property is a read/write property that can also be used to add new items to the cache. If the key specified as the argument of the Item property does not exist, a new entry is created. Otherwise, the existing entry is overwritten.

Cache["MyItem"] = value;

The data stored in the cache is generically considered to be of type object, whereas the key must be a case-sensitive string. When you insert a new item in the cache using the Item property, a number of default attributes are assumed. In particular, the item is given no expiration policy, no remove callback, and a normal priority. As a result, the item will stay in the cache indefinitely, until programmatically removed or until the application terminates. To specify any extra arguments and exercise closer control on the item, use the Insert method of the Cache class instead.

Methods of the Cache Class

The methods of the Cache class let you add, remove, and enumerate the items stored. Methods of the Cache class are listed and described in Table 2.

Table 2. Cache Class Methods
AddAdds the specified item to the cache. It allows you to specify dependencies, expiration and priority policies, and a remove callback. The call fails if an item with the same key already exists. The method returns the object that represents the newly added item.
GetRetrieves the value of the specified n item from the cache. The item is identified by key. The method returns null if no item with that key is found. (This method is used to implement the get accessor of the Item property.)
GetEnumeratorReturns a dictionary enumerator object to iterate through all the valid items stored in the cache.
InsertInserts the specified item into the cache. Insert provides several overloads and allows you to specify dependencies, expiration and priority policies, and a remove callback. The method is void and, unlike Add, overwrites an existing item having the same key as the item being inserted. (This method is used to implement the set accessor of the Item property.)
RemoveRemoves the specified item from the cache. The item is identified by the key. The method returns the instance of the object being removed or null if no item with that key is found.

Both the Add and Insert methods don’t accept null values as the key or the value of an item to cache. If null values are used, an exception is thrown. You can configure sliding expiration for an item for no longer than one year. Otherwise, an exception will be raised. Finally, bear in mind that you cannot set both sliding and absolute expirations on the same cached item.


Add and Insert work in much the same way, but a couple of differences make it worthwhile to have both on board. Add fails (but no exception is raised) if the item already exists, whereas Insert overwrites the existing item. In addition, Add has just one signature, while Insert provides several different overloads.

An Interior View

The Cache class inherits from Object and implements the IEnumerable interface. It is a wrapper around an internal class that acts as the true container of the stored data. The real class used to implement the ASP.NET cache varies depending on the number of affinitized CPUs. If only one CPU is available, the class is CacheSingle; otherwise, it is CacheMultiple. In both cases, items are stored in a hashtable and there will be a distinct hashtable for each CPU. It turns out that CacheMultiple manages an array of hashtables. Figure 1 illustrates the architecture of the Cache object.

Figure 1. The internal structure of the ASP.NET cache.

The hashtable is divided into two parts—public and private elements. In the public portion of the hashtable are placed all items visible to user applications. System-level data, on the other hand, goes in the private section. The cache is a resource extensively used by the ASP.NET runtime itself; system items, though, are neatly separated by application data and there’s no way an application can access a private element on the cache.

The Cache object is mostly a way to restrict applications to read from, and write to, the public segment of the data store. Get and set methods on internal cache classes accept a flag to denote the public attribute of the item. When called from the Cache class, these internal methods always default to the flag that selects public items.

The hashtable containing data is then enhanced and surrounded by other internal components to provide a rich set of programming features. The list includes the implementation of a least recently used (LRU) algorithm to ensure that items can be removed if the system runs short of memory, dependencies, and removal callbacks.


On a multiprocessor machine with more than one CPU affinitized with the ASP.NET worker process, each processor ends up getting its own Cache object. The various cache objects are not synchronized. In a Web garden configuration, you can’t assume that users will return to the same CPU (and worker process) on subsequent requests. So the status of the ASP.NET cache is not guaranteed to be aligned with what the same page did last time.

Top 10
SG50 Ferrari F12berlinetta : Prancing Horse for Lion City's 50th
The latest Audi TT : New angles for TT
Era of million-dollar luxury cars
Game Review : Hearthstone - Blackrock Mountain
Game Review : Battlefield Hardline
Google Chromecast
Keyboards for Apple iPad Air 2 (part 3) - Logitech Ultrathin Keyboard Cover for iPad Air 2
Keyboards for Apple iPad Air 2 (part 2) - Zagg Slim Book for iPad Air 2
Keyboards for Apple iPad Air 2 (part 1) - Belkin Qode Ultimate Pro Keyboard Case for iPad Air 2
Michael Kors Designs Stylish Tech Products for Women
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
Popular Tags
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone