To read the article online, visit

.NET Data Caching, Part 2

By Dimitrios Markatos

  • Read Part 1

  • In Part 1 we looked at how to add an element to the cache, retrieve an element, and remove an element. In this part we'll look at the Cache.Insert method, which allows for more powerful semantics with inserting an item into the data cache.

    Inserting an Item into the Cache

    As we saw earlier, inserting an item into the data cache is as simple as saying Cache("key") = value. Items can also be inserted into the cache using the Insert method, which allows for more powerful semantics on how the item in the cache should be handled. Specifically, the Insert method has four overloaded forms, as shown below:

    1. Insert(key as String, value as Object) - Inserts the object value into the cache, giving the item the key name key. This is semantically equivalent to using Cache("key") = value.
    2. Insert(key as String, value as Object, dependencies as CacheDependency) - Inserts the object value into the cache with key name key and dependencies specified by the dependencies parameter. We'll discuss cache dependencies shortly.
    3. Insert(key as String, value as Object, dependencies as CacheDependency, absoluteExpiration as DateTime, slidingExpiration as TimeSpan) - Inserts the object value into the cache with key name key, dependencies dependencies, and (time-based) expiration policies. Expiration policies, as we'll discuss soon, specify when the item should be evicted from the cache.
    4. Insert(key as String, value as Object, dependencies as CacheDependency, absoluteExpiration as DateTime, slidingExpiration as TimeSpan, priority as CacheItemPriority, onRemoveCallBack as CacheItemRemovedCallback) - Inserts the object value into the cache with key name key, dependencies dependencies, (time-based) expiration policies, a cache priority, and a callback delegate. The priority specifies how important it is for the cache item to remain in the cache. That is, items with a lower priority will be evicted from the cache before items with a higher priority. The callback delegate provides a means for you to create your own function that is automatically called when the item is evicted from the cache.

    The above list of the various forms of the Insert method may look quite daunting. Most often you'll likely use either form 1, 2, or 3. Let's take a moment to discuss the CacheDependency and absolute and sliding time parameters.

    Recall that information stored in the data cache is being stored on the Web server's memory. In a perfect world, when an item is added to the cache using Insert(key, value) or Cache("key") = value, the item will remain in the cache forever. Unfortunately this is not plausible in the real world. If the computer the Web server runs on is rebooted, or shuts off, for example, the cache will be lost. Even if the Web server machine is running, you may lose items from the cache.

    To see why, imagine that your Web server has allocated one MB of memory for storing items in the data cache. Now, imaging that you've added a number of items to the data cache such that you've used exactly 1 MB of memory. Great. Now, what happens when you add another item to the data cache? In order for the new item to "fit," the data cache needs to make room for it by removing an existing item. The existing item that is chosen to be removed is said to be evicted.

    There may be times when you don't want an item to exist in the cache indefinitely. For example, say that you were displaying an XML file in an ASP.NET DataGrid. (See XML, the DataSet, and a DataGrid for an article illustrating how to accomplish this!) Rather than load the XML file into a DataSet and bind the DataSet to the DataGrid each page view, you may opt to cache the DataSet in the data cache. This option would work great until the XML file was altered; at that point, if you were still displaying the cached DataSet the user would be seeing stale information.

    To overcome this problem, you can add the DataSet to the data cache, but specify that the XML file it represents is a cache dependency. By setting this file as a cache dependency, when the file changes the DataSet will be automatically evicted from the cache. That means the next time the DataSet is attempted to be read from the cache, it will not be found (since it has been evicted) and will be recreated by repopulating the DataSet from the XML file. This is desired since the XML file has changed since the DataSet was last cached. In order to insert an item with a cache dependency, you can do:

    Cache.Insert("key", myDataSet, New CacheDependency(Server.MapPath("data.xml")))

    If you wish to have the cache item evicted from the cache in an absolute time, say, five minutes from when it was inserted into the cache, you can use the third form of the Insert method, whose fourth parameter expects a DateTime value specifying the absolute time. The following code illustrates how to add an item to the cache that will expire five minutes from when it was added and has no cache dependencies:

    Cache.Insert("key", value, Nothing, DateTime.Now.AddMinutes(5), TimeSpan.Zero)

    In C# you would use null instead of Nothing to signify that you do not want a cache dependency.

    Note that since we do not want to specify a sliding time expiration, we set the last parameter to TimeSpan.Zero. Whereas an absolute time specifies that the item should be evicted from the cache at a specific time, the sliding time eviction parameter specifies that the cache item should be evicted if it is not referenced in a certain timespan. That is, if we set the timespan parameter to, say, TimeSpan.FromSeconds(30), the cache item will be evicted if it is not referenced within 30 seconds. If it is referenced within 30 seconds, it will be evicted if it's not referenced in another 30 seconds from when it was last referenced, and so on. An example of this would be:

    Cache.Insert("key", value, Nothing, DateTime.Now, TimeSpan.FromSeconds(30), TimeSpan.Zero)

    Note that when using the sliding time expiration parameter, the absolute expiration parameter value does not matter. That is, it is automatically set to DateTime.Now and has the sliding time added to it to determine the absolute time the cache item should expire. Of course, if the item is referenced within that time period, the calculation is redone and the absolute expiration time is reset.

    Before we move on to some examples, let's take a quick look at the CacheItemRemovedCallback delegate. Recall that you can set this in the fourth overloaded form of the Insert method. The CacheItemRemovedCallback specifies a function that is called when the item has been evicted from the cache. To use the CacheItemRemovedCallback you need to first create a function that has the definition:

    Sub CallbackFunction(String, Object, CacheItemRemovedReason)

    The CacheItemRemovedReason is an enumeration that explains why the item was removed from the cache. Its entries include:

    1. DependencyChanged - the item was removed because its cache dependency was changed.
    2. Expired - the item was removed because it expired (either by absolute or sliding time expiration).
    3. Removed - the item was explicitly removed via the Remove method.
    4. Underused - the item was evicted by the cache because the system needed to free up memory.

    To add a CacheItemRemovedCallback function to an added cache item you will need to create the appropriate function and a delegate variable that is wired up to the function, as shown below:

    'You would use onCacheRemove as the input parameter for the
    'CacheItemRemovedCallback parameter in the fourth form of the Insert method
    Dim onCacheRemove As CacheItemRemovedCallback
    OnCacheRemove = New CacheItemRemoved(AddressOf  Me.CheckCallback)
    ' Now, create the function
    Sub CheckCallback (str As String, obj As Object, reason As CacheItemRemovedReason)
    	Response.Write ("Cache was removed because : " & reason)		
    End Sub

    I am not going to go into detail discussing the CacheItemPriority option, since I've found very few real-world uses for this property (in designing Web applications). To learn more about this enumeration and how to use it with the Insert see the technical documentation.

    At this point we've discussed the basics of data caching and the specifics of the Cache.Insert method. In Part 3 we'll examine a real-world caching example: a pagable DataGrid that uses a cached DataSet to save on database hits.

  • Read Part 3!

  • Article Information
    Article Title: ASP.NET..NET Data Caching, Part 2
    Article Author: Dimitrios Markatos
    Published Date: October 9, 2002
    Article URL:

    Copyright 2021 QuinStreet Inc. All Rights Reserved.
    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers