Caching in ASP.NET
There are two types of caching available in ASP.NET: page output caching and data caching. From the two, page output caching is the easier to use, so let’s start with that one.
Page Output Caching
Page Output Caching simply bypasses the page life-cycle by handling a cached version of the page instead of regenerate it from scratch every time. You can cache the whole page or a portion of the page nested into a user control. To enable page output caching, simply insert the OutputCache directive after the Page (or Control) directive on the page. OutputCache has the following parameters:
- Duration: the time in seconds to cache the page.
- Location: doesn’t supported in UserControls.
- Shared: sets whether or not the cached user control should be used in multiple pages.
- SqlDependency: a table in a database on which the caching depends on.
- VarByCustom: set up custom cache dependencies (set it in the global.asax)
- VarByHeader: a semicolon-separated list of HTTP headers to cache different versions of the page.
- VarByParam: a semicolon-separated list of query string parameters to cache different versions of the page.
- VarByControl: a semicolon-separated list of control IDs to cache different versions of the page.
You can enable caching of a page programmatically by calling the Cache object’s (exposed by Response) SetCacheability(Server) method.
You can cache application data programmatically by using the Cache object exposed by Page. There are two methods to do so, with the exact same overloads: Add and Insert. Insert is void, so it has no return value, but if you insert an object to the class on an existing key, it will be overwritten. Add returns the object inserted to the cache, but doesn’t writes over the possible existing item, and throws no exceptions (so you’d never know the adding failed).
The next table shows the overloads:
|Overloads of the Cache.Insert and Cache.Add methods|
|String Key, Object Value||Adds an object to the cache with the specified key.|
|+CacheDependency dependency||Adds an object to the class with the specified dependency.|
|+ DateTime absoluteExpiration, DateTime slidingExpiration||Specifies whether to use absolute or sliding expiration.|
The other two overloads are a bit too specific, but you can refer to MSDN to gain deeper understanding. Now let’s see a code to insert something into the cache, and then retrieve it:
DataTable dt = new DataTable();
Cache.Insert("Key", dt, new CacheDependency("dependent.xml"), new DateTime(), new TimeSpan(1,0,0));
if (Cache["Key"] == null)
Cache.Insert("Key", dt, new CacheDependency("dependent.xml"), new DateTime(), new TimeSpan(1, 0, 0));
dt = (DataTable)Cache["Key"];
This example inserts a DataTable into the cache which depends on an XML file named dependent.xml, and stores it for an hour whenever its requested. To retrieve values from the cache, you should always check for a null value to avoid NullReferenceExceptions, and insert the object if the key isn’t found.
It’s worth knowing that when you are using InProc session state, you are actually working with the Cache object, hence the similarities. Although you cannot access session objects using the Cache.
There are three cases when cached data expires:
- During scavenges (when server memory is running low).
- Changes in cache dependencies
I think these cases require no further explanations, it just worth knowing.