RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Take Advantage of ASP.NET 2.0's Data Caching Techniques, Part 2 : Page 6

The second half of this two-part article looks at ASP.NET 2.0's new SQL cache invalidation support, and shows you how to use the Caching API to speed up your ASP.NET applications.

Detecting Cache Invalidation
The onRemoveCallback parameter for the Add and Insert methods of the ASP.NET Cache object, shown in Table 2, is a reference to a delegate (event handler) that handles the CacheItemRemoved event. This event is raised when an item is removed from the cache for any reason, including invalidation through a dependency or through the cache becoming full—whereupon the least used and lowest priority items are removed.

You can handle the CacheItemRemoved event, and get information about the event, the item that was removed, and the reason:

   Sub MyItemRemoved(key As String, value As Object, _
     reason As CacheItemRemovedReason)
     ' reason will be one of:
     ' Expired | Removed | Underused | DependencyChanged   
     ' re-create item and add back to cache as required
   End Sub
Inside the event handler, you might decide to recreate the item and store it back in the cache (depending on the reason or some other factor), or take whatever other action is appropriate for your application. To register this event handler when you create a CacheDependency, you simply specify it as the last parameter of the Insert or Add method:

   Cache.Insert("key", value, Nothing, _
      DateTime.Now.AddMinutes(10), _
      TimeSpan.Zero, CacheItemPriority.High, _
      New CacheItemRemovedCallback(AddressOf MyItemRemoved))
Author's Note: See the .NET Framework SDK topic "CacheItemRemovedCallback Delegate" in the "Reference | Class Library" section for more details.

Figure 7. Cache API Features: The example page demonstrates some of the features of the Cache API.
The example page named cache-api.aspx demonstrates many of the features just described for using the Cache API, including adding different types of values with differing invalidation rules, creating a chained dependency, detecting cache invalidation, and enumerating the items stored in the Cache. Figure 7 shows the page, and you can see that it contains controls to refresh the page, insert a String value into the cache, add an array of Integer values to the cache, and insert a DataSet into the cache. Each item has a different set of properties for the created CacheDependency; for example it caches the String value from the Textbox with a ten second timeout using:

   Cache.Insert("MyTextBox", txtToCache.Text, Nothing, _
      DateTime.Now.AddSeconds(10), _
      TimeSpan.Zero, CacheItemPriority.High, _
      New CacheItemRemovedCallback(AddressOf ItemRemoved))
However, it adds the array of Integers to the cache using the Add method, which fails if an item with the same key is already in the cache. The following code adds the array to the Cache object, tests whether it succeeded and displays the message in Figure 7 if the item already exists:

   ' add array of Integers to cache using Add method
   Dim aInt() As Integer = {0,1,2,3,4}
   If Not Cache.Add("MyIntArray", aInt, Nothing, _
      DateTime.MaxValue, _
      New TimeSpan(0, 0, 5), CacheItemPriority.High, _
      New CacheItemRemovedCallback(AddressOf ItemRemoved)) _
      Is Nothing Then
      ' add warning to the StringBuilder that 
      ' displays messages in the page
         "- item already exists, cache was not updated<br />")
   End If
Notice how, this time, the code specifies the expiration as a "sliding" time value so that it will expire five seconds after the last access, rather than at a fixed ("absolute") time. To achieve this it specifies the absolute expiration parameter as DateTime.MaxValue, and the sliding expiration parameter as a TimeSpan instance.

You can see from the Figure 7 that the page also displays a list of items in the cache. It uses the following code to do this:

   ' display contents of the ASP.NET Cache
   If Cache.Count > 0 Then
     cc.Append("<b>Contents of the ASP.NET Cache (" _
        & Cache.Count.ToString() & " items):</b><br />")
     For Each item As Object In Cache
       cc.Append("Key:'" & item.Key & "' Type:" _
          & item.Value.GetType().ToString() & "<br />")
     cc.Append("<b>ASP.NET Cache is empty</b>")
   End If
   ' show contents of StringBuilder in the Label control 
   ' with the ID "cachecontents"
   cachecontents.Text = cc.ToString()
Figure 8. Output from the ItemRemoved Handler: The figure shows the messages displayed when the DataSet is removed from the cache.
In Figure 8, you can see another feature of this page. The code to add the DataSet to the cache looks like this:

   ' code here to create DataSet and fill with some rows
   ' ......
   ' create array containing cache key to depend on
   Dim aKeys(0) As String
   aKeys(0) = "MyTextBox"
   ' create a dependency on the cache key in the array
   Dim dep As New CacheDependency(Nothing, aKeys)
   ' insert DataSet into Cache with dependency on 
   ' String value from Textbox
   Cache.Insert("MyDataSet", ds, dep, _
      DateTime.Now.AddMinutes(5), _
      TimeSpan.Zero, CacheItemPriority.High, _
      New CacheItemRemovedCallback(AddressOf ItemRemoved))
The result is that the DataSet can be cached only when the String value from the Textbox is also cached. The version 2.0 copy of this page also contains the event handler named ItemRemoved, which is referenced above in all the statements that create CacheDependency instances. This event handler executes when any item is removed from the cache. The following code shows the event handler.

   Sub ItemRemoved(key As String, value As Object, _
      reason As CacheItemRemovedReason)
      ' display details of item removed from cache and reason
      op.Append("ItemRemoved event raised at " _
         & DateTime.Now.ToString() & "<br />")
      op.Append("- removed item '" & key & "', Reason is '" _
         & reason.ToString & "'<br />")
   End Sub
Figure 8 shows the output from this event handler when you try to add the DataSet to the cache without adding the String value first. However, this event handler runs only when a cache invalidation occurs while the page is executing.

Adding CacheDependencies Programmatically
You can also use the CacheDependency class with page output caching. To do that, create a CacheDependency instance, and assign it to the current ASP.NET page using the methods of the Response object. The HttpResponse class (in the System.Web namespace) implements the Response instance for an ASP.NET page, and has a series of properties and methods that you can use to manipulate the output cache settings for the page programmatically.

The AddCacheItemDependency method takes a String cache key name, and makes the output cache dependent on this item. Likewise, the AddCacheItemDependencies method does the same for the items specified by an ArrayList of cache key names. Meanwhile the AddFileDependency and AddFileDependencies methods do the same for a file path/name or an ArrayList of file path/names.

Author's Note: See the .NET Framework SDK topic "HttpCachePolicy Members" in the "Reference | Class Library" section for more details.

The example page named file-dependency.aspx demonstrates how you can create a CacheDependency in code, and use it to control output caching of an ASP.NET page. It declares an OutputCache directive in the page that causes the whole page to be cached for five minutes, and does not vary the cache through any values (parameters) that may be posted to the page:

   <%@OutputCache Duration="300" VaryByParam="None" %>
The page also contains an XmlDataSource control that takes its data from an XML file named slides.xml located in the same folder as the page:

   <asp:XmlDataSource id="XmlDataSource1" 
      runat="server" DataFile="slides.xml" />
Figure 9. File Cache Dependency: The page shows the results of programmatically adding a CacheDependency for a disk file.
The remaining page content is a GridView that displays the data in the XML document, and a button to cause a postback. However, in the Page_Load event, code that runs when the page is executed not only displays the current time in a Label control at the top of the page, but also sets up a dependency on the slides.xml file:

   ' create File Dependency and attach to the cache
   Dim dep As New CacheDependency(Server.MapPath("slides.xml"))
If you run this page (see Figure 9) and then refresh it, you'll see that the server delivers the output-cached copy until the five minutes specified in the OutputCache directive have elapsed. However, if you open the XML file in a text editor and edit the values, you'll see that the cached page is invalidated immediately, and the new values are displayed when you refresh the page.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date