When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, December 18, 2002

Displaying Cached XML Data in a DataGrid, and Intelligently Refreshing the Data

By Scott Mitchell


Introduction


One of the coolest and most powerful aspects of the .NET Framework is the built-in caching APIs. These caching APIs make caching through ASP.NET Web pages painfully simple. When discussing caching with regards to an ASP.NET Web page there are two classes of caching: output caching and data caching.

- continued -

Output caching is the caching of the HTML output of an ASP.NET Web page. This cached HTML is stored on disk and is cached for a specific period of time (say 30 seconds). With data caching, programming objects (such as integers, DataSets, ArrayLists, etc.) are stored in an in-memory cache. Items stored in the data cache can have their expiration specified by a sliding time scale, an absolute time scale, or via a cache dependency. A cache dependency can be a file or a directory in the file system, or a key in the cache. When the dependency changes - the file is modified, the directory is altered, or the cache item is altered or evicted - the item with the cache dependency is evicted from the cache.

In this article we will first look at caching a DataSet in the data cache, and binding this cached DataSet to a DataGrid. Specifically, this cached DataSet will contain the data from an XML file residing on the Web server's file system. A cache dependency will then be used so that the cached DataSet is evicted from the data cache when the XML file's contents are altered. In essence we will be examining how to create a DataGrid that displays cached data, but whose data is never stale! (That is, whenever the data changes, the cached version of the data is updated as well.)

Displaying XML Data in a DataGrid


In a previous 4Guys article, XML, the DataSet, and a DataGrid, I looked at how to display XML data in a DataGrid. The first step in accomplishing this is reading the XML data into a DataSet. Once we have the data in a DataSet, we can simply bind the DataSet to the DataGrid's DataSource and then call the DataGrid's DataBind() method.

For More Information on the DataGrid...
If you're not familiar with the DataGrid Web control I would encourage you to first read an earlier article of mine: An Extensive Examination of the DataGrid Web Control. It is a multi-part series that covers the ins and outs of the DataGrid Web control.

Reading XML data into a DataSet is incredibly simple thanks to the DataSet's ReadXml() method. This method takes in a string parameter as the filename to the XML file.

'Create a DataSet
Dim myDataSet as New DataSet()

'Read the XML file using the ReadXml method
myDataSet.ReadXml(Server.MapPath("books.xml"))

In the above example, the Server.MapPath() method is used to obtain the full physical path to the books.xml file. (For more information on Server.MapPath() be sure to read: Using Server.MapPath().)

Once we have a DataSet populated with the results of an XML file, we can display the DataSet in a DataGrid Web control using the following two lines of code:

DataGridID.DataSource = myDataSet
DataGridID.DataBind()

The following code snippet shows the complete code for an ASP.NET Web page that displays the contents of the file books.xml file.

<%@ Import Namespace="System.Data" %>
<script runat="server">
    sub Page_Load(sender as Object, e as EventArgs)
        Dim myDataSet as New DataSet()
    
        myDataSet.ReadXml(Server.MapPath("books.xml"))
    
        dgBooks.DataSource = myDataSet
        dgBooks.DataBind()
    end sub
</script>

<asp:datagrid id="dgBooks" runat="server" />
[View a Live Demo!]

Caching the DataSet


Now that we have seen how to populate a DataSet with the contents of an XML file, let's turn our attention to caching this DataSet in the data cache. This article does not intend to be a thorough examination of the data cache, as there are already a number of articles already on this topic. If you are interested in learning more about caching options available with ASP.NET, I'd highly recommend Scott McFarland's Caching with ASP.NET article.

To bind the DataGrid to a cached DataSet, we first must check that the DataSet is in the cache. After all, it may have never been added, or it may have been evicted from the cache for one of any number of reasons. To determine if an item is in the cache, we can simply check to see if the item is Nothing. (In C# you'd check to see if the cache item equaled null.) The following code checks to see if the cache item authorsDS is in the cache or not.

If Cache("authorsDS") is Nothing then
  'There is no authorsDS item in the Cache...
End If

In the case that there is no authorsDS item in the cache, we want to add it. This can be accomplished using the Cache.Insert() method. Before adding the DataSet to the cache, though, we must populate it from the XML file, as we saw earlier. This code, then, looks like:

If Cache("authorsDS") is Nothing then
  'There is no authorsDS item in the Cache...
  Dim myDataSet as New DataSet()
  myDataSet.ReadXml(Server.MapPath("books.xml"))

  'Add it to the Cache
  Cache.Insert("authorsDS", myDataSet)
End If

When the end of this conditional statement is reached, we know for certain that there exists a cache item named authorsDS (that should have a cached DataSet populated from the books.xml file). If, when the page is visited, the cache item does not exist, it is created and added to the cache. If, on the other hand, when the page is visited the cache item does exist, then we don't need to populate the DataSet with the XML file contents, since the contents are already populated in a cached DataSet.

All that's left to do here is bind the cached DataSet to a DataGrid, which is accomplished using the following complete code example:

<%@ Import Namespace="System.Data" %>
<script runat="server">
    sub Page_Load(sender as Object, e as EventArgs)
       If Cache("authorsDS") is Nothing then
          'There is no authorsDS item in the Cache...
          Dim myDataSet as New DataSet()
          myDataSet.ReadXml(Server.MapPath("books.xml"))

          'Add it to the Cache
          Cache.Insert("authorsDS", myDataSet)
          
          lblMessage.Text = "DataSet populated from XML file..."
        End If
    
        'Set the DataGrid's DataSource to the cached DataSet
        dgBooks.DataSource = Cache("authorsDS")
        dgBooks.DataBind()
    end sub
</script>

<asp:datagrid id="dgBooks" runat="server" />
<asp:label id="lblMessage" runat="server" Font-Italic="True" />

Notice that a Label Web control was added (lblMessage) that is used to display a helpful debugging message when the DataSet was not found in the cache. If you try this example on your own computer, you'll find that the first time you visit the page it indicates that the DataSet was populated from the XML file; however, if you reload the page, this message does not appear, since the DataSet is cached, and the DataGrid is using the cached version.

Caching the Data in a More Intelligent Manner


One downside, though, is that when using cached data, the data may become stale. For example, if you visit the page with the cached DataSet once, to load the DataSet into the cache, and then the contents of the XML file are changed, the cached DataSet page will continue to show the cached data. That is, your users will see the data prior to the change in the XML file.

Ideally we'd like to be able to have the cached data reside in the cache so long as the underlying XML data doesn't change. To put it another way, as soon as the XML file's contents change, we want the cached DataSet to be evicted from the cache. We can accomplish this goal using cache dependencies.

As mentioned in the Introduction, cache dependencies can be a file (or files) or a directory in the file system, or a key in the cache. When the dependency changes - the file is modified, the directory is altered, or the cache item is altered or evicted - the item with the cache dependency is evicted from the cache. This sounds exactly like what we need! Essentially, the books.xml file will become the cache dependency for the cached DataSet. This will cause the cached DataSet to be evicted from the cache whenever the books.xml file is altered.

To add an item to the cache with a cache dependency, we simply need to use an alternate version of the Cache.Insert() method. Specifically, we need to pass in a CacheDependency object instance as the third parameter to Cache.Insert(). This requires just a small edit to our earlier code sample, which now gives us:

<%@ Import Namespace="System.Data" %>
<script runat="server">
  sub Page_Load(sender as Object, e as EventArgs)
    If Cache("authorsDS") is Nothing then
      'There is no authorsDS item in the Cache...
      Dim myDataSet as New DataSet()
      myDataSet.ReadXml(Server.MapPath("books.xml"))

      'Add it to the Cache
      Cache.Insert("authorsDS", myDataSet, _
              New CacheDependency(Server.MapPath("books.xml")))
          
      lblMessage.Text = "DataSet populated from XML file..."
    End If
    
    'Set the DataGrid's DataSource to the cached DataSet
    dgBooks.DataSource = Cache("authorsDS")
    dgBooks.DataBind()
  end sub
</script>

<asp:datagrid id="dgBooks" runat="server" />
<asp:label id="lblMessage" runat="server" Font-Italic="True" />

And that's all there is to it! Now, when you try the above code on your computer you'll find that when you first visit the page the message "DataSet populated from XML file..." appears, but on subsequent visits, the message is no longer there. The cool part - if you edit the books.xml file (say add a new book element), and then revisit the page, you'll note that the DataGrid is displaying the new book and that the "DataSet populated from XML file..." message has appeared again. This is because the cached DataSet is evicted from the cache whenever edits occur to the underlying XML file.

For More Information...
For more information on caching and using cache dependencies, be sure to check out Dino Esposito's article Using Session and Application Objects in ASP.NET. For a tutorial showing how to use on-demand cache eviction for data in a SQL Server database (as opposed to in an XML file) see Donny Mack's Invalidating an ASP.NET Web Application Cache Item from SQL Server.

Conclusion


In this article we saw how to accomplish a number of things, which include: populating a DataSet with data from an XML file; caching a DataSet in the data cache; and using cache dependencies to provide on-demand cache eviction when the underlying XML data is altered. This approach has the performance benefits inherent with caching, and removes one of the primary disadvantages of caching: stale data.

Happy Programming!

  • By Scott Mitchell



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article