<span class="subhead">Introduction to Data Caching</span>
<p>
ASP+ provides a full featured cache engine that can be utilized by pages to store and retrieve arbitrary objects across HTTP requests. The ASP+ cache is private to each application and stores objects in memory. The lifetime of the cache is equivalent to the lifetime of the application--that is, when the application is restarted, the cache is recreated.
<p>
The cache provides a simple dictionary interface that allows programmers to easily place objects in the cache and later retrieve them from it. In the simplest case, placing an item in the cache is just like adding an item to a dictionary:
<div class="code"><xmp>
Cache["mykey"] = myValue;
</xmp></div>
Retrieving the data is just as simple:
<div class="code"><xmp>
myValue = Cache["mykey"];
if(myValue != null )
{
DisplayData(myValue);
}
</xmp></div>
For applications that need more sophisticated functionality, the ASP+ cache supports scavenging, expiration, and file and key dependencies.
<p>
<ul>
<li><b>Scavenging</b> refers to the fact that the cache will attempt to remove infrequently-used or unimportant items if memory becomes scarce. Programmers that wish to control how scavenging occurs can provide hints to the scavenger when items are inserted that indicate the relative cost of creating the item and the relative rate at which the item must be accessed to remain useful.
<p>
<li><b>Expiration</b> allows programmers to give cache items lifetimes, which can be explicit (expire at 6:00) or can be relative to an item's last use (expire 20 minutes after the item has last been accesssed). After an item has expired, it will be removed from the cache and future attempts to retrieve it will return the null value unless the item is reinserted into the cache.
<p>
<li><b>File and key dependencies</b> allow the validity of a cache item to be based on an external file or upon another cache item. If a dependency changes, the cache item is invalidated and removed from the cache. As an example of how a programmer might use this functionality, consider the following scenario: an application reads financial information from an XML file that is periodically updated. The application processes the data in the file and creates a graph of objects that represent that data in a consumable format. The application caches that data and inserts a dependency on the file from which the data was read. When the file is updated, the data is removed from the cache and the application can re-read it and reinsert the updated copy of the data.
</ul>
<a name="samples">
<span class="subhead">Using the Data Cache</span>
<p>
The following sample shows a simple use of the cache. It executes a database query and caches the result, which it continues to use for the lifetime of the application. When you run the sample, note the message at the bottom of the page. When first requested, it will indicate that the data was explicitly retrieved from the database server. After refreshing the page, the page will note that the cached copy was used.
The next example shows a cache item that depends on an XML file. It is similar to the first example, although in this case the data is retrieved from an XML data source instead of a database server. When the data is cached, the XML file is added as a dependency.
<p>
When a new record is added using the form at the bottom of the page, the XML file is updated and the cached item must be recreated.
Note that a file dependency is added by using <b>Cache.Insert</b> and supplying a <b>CacheDependency</b> object referencing the XML file.
<div class="code"><xmp>
Cache.Insert("MyData", Source, new CacheDependency(Server.MapPath("authors.xml")));
</xmp></div>
A cache item can depend on a single or multiple files or keys. As mentioned above, an application can also set expiration policy on a cache item. To set an absolute cache expiration time, code like the following could be used:
The relevant parameter is the call to DateTime.Now.AddHours(1), which indicates that the item expires 1 hour from the time it's inserted. The final argument, TimeSpan.Zero indicates that there is no relative expiration policy on this item.
<p>
An example of setting a relative expiration policy is shown by the following code. It inserts an item that expires 20 minutes after it's last accessed. Note the use of DateTime.MaxValue, which indicates that there is no absolute expiration policy on this item.
Developers should be aware that there is a race condition inherent to caching that can occur when items are created and cached when they're found to be absent. Consider the following scenario: a page contains the following code:
<div class="code"><xmp>
myValue = Cache["mykey"];
if(myValue != null )
{
DoSomething(myValue);
}
else
{
myValue = CreateData();
Cache["mykey"] = myValue;
}
</xmp></div>
<p>
If the data is not cached, and several requests are received in a short amount of time, the item can be created multiple times. This can happen because in the amount of time it takes for the first request to create the item, the subsequent requests are handled and find the cache item missing, as well. This may or may not be an issue for an application, depending on the cost of creating the item and the semantics it involves. If it is an issue, applications should consider either creating the data at application startup (e.g. handle the <b>Application_OnStart</b> event) and caching it then or synchronizing access to the cached item using a technique similar to that shown in the following code.
<div class="code"><xmp>
// assumes declaration of class/page level variable
private static String cacheSynchronize;
myValue = Cache["mykey"];
if(myValue != null )
{
DoSomething(myValue);
}
else
{
// item isn't cached: acquire lock, create and cache
lock(cacheSynchronize)
{
// has it been updated before we got the lock?
myValue = Cache["mykey"];
if( null == myValue )
{
myValue = CreateData();
Cache["mykey"] = myValue;
}
DoSomething(myValue);
}
}
</xmp></div>
<p>
Note that is it's relatively cheap to create the item or if creating it multiple times has no adverse effects, than this race condition won't hurt you.
<h4>Section Summary</h4>
<ol>
<li>Data Caching allows arbitrary objects to be cached programmatically
<li>The ASP+ cache supports expiration and dependencies
<li>The cache is scoped to an application and its lifetime is equivalent to the lifetime of the application