To read the article online, visit http://www.4GuysFromRolla.com/articles/012407-1.aspx

Accessing and Updating Data in ASP.NET: Declaratively Caching Data

By Scott Mitchell


Introduction


The ASP.NET 2.0 data source controls provide a declarative means for accessing and working with data. Simply set a few properties of the data source control, bind it to a data Web control, and, voila, data is being retrieved and displayed without having written a single line of code!

In addition to working with data declaratively, the data source controls can also cache data declaratively. Caching is a common technique used in data-driven applications to boost performance, and works by storing database data in memory where it can be more efficiently accessed. ASP.NET provides the data cache, which is a programmatically-accessible cache that is commonly used to store database results. See Caching in ASP.NET for more details on using the data cache and other caching options in ASP.NET.

What's worth noting about the data source controls is that they offer declarative access to the data cache. By simply setting a few properties, the data source controls will happily store their retrieved data in the data cache. Then, the next time the data source is asked to retrieve data, they'll pull that data from the cache instead of returning to the database. In this article we'll explore how to setup a data source control so that it stores it caches its results. Read on to learn more!

A Quick Primer on Caching


Caching is a technique for improving performance by moving data from some expensive data store to one that is less so. By "expensive" I mean that there is a performance cost associated with working with the data and by "data store" I mean some location where data is stored: a database, a file, memory, and so forth. The canonical caching example is taking information from a database and storing it in an application's memory, since an application can read from its memory many orders of magnitude faster than it can read the same data from a remote database server.

Caching carries with it some limitations. Almost always, the more efficent data store has less storage space than the slower store. That is, chances are the database holds a lot more information than can fit in the application's memory. Therefore, not all data can be cached. Moreover, when adding data to the cache, other cached information might need to be evicted from the cache in order to make room.

Also, caching imposes a disconnect between data the application sees and the source data itself. If the source data is updated or deleted, the application working with a cached copy won't know that it's data has become stale until it returns to the original data store and determines that this, indeed, is the case. For this reason, data is typically only cached for a pre-determined duration, after which the data is automatically evicted. This places an upperbound on how long the cached data may be stale. (ASP.NET 2.0 offers SQL cache dependencies, which is a more proactive technique for determining if the cached data has become stale. This article does not explore SQL cache dependencies, but see the "Further Readings" section at the end for more information on this topic.)

The data cache is the cache store commonly used by ASP.NET applications. It is an in-memory cache that is accessible through the Cache object. The data cache provides dictionary-like access to its contents. To add an item to the cache, specify a key for that cache item, where the key is a string. Likewise, to retrieve an item from the cache, refer to it via its key. The following code snippet shows reading and writing to the data cache:

// C#
Cache["key"] = ObjectToCache;  // write to the cache
object myData = Cache["key"];  // read from the cache

' VB
Cache("key") = ObjectToCache         ' write to the cache
Dim myData As Object = Cache("key")  ' read from the cache

Caching Data Retrieved from the Data Source Controls


The ObjectDataSource, SqlDataSource, AccessDataSource, and XmlDataSource controls all contain properties that instruct the data source control to cache its data in the data cache. This caching occurs automatically and requires no code from us, the page developer. The key properties are:
  • EnableCaching - a Boolean value that indicates whether or not caching should be applied. Defaults to False. You will need to set this to True to instruct the data source control to employ caching.
  • CacheDuration - an Integer value that indicates the duration the data should be cached (in seconds).
  • CacheExpirationPolicy - specifies the cache expiration behavior; can be set to Absolute or Sliding. Absolute means that the cached item will be evicted CacheDuration seconds from when the item is initially inserted into the cache. Sliding means that the item will be evicted CacheDuration seconds after the last time the data is accessed from the cache. The default is Absolute.
  • CacheKeyDependency - a String value that specifies an additional item in the cache that serves as a dependency. If this value is specified, then whenever the cache item CacheKeyDependency is modified, the data source will automatically evict its data from the cache as well.
The SqlDataSource and ObjectDataSource controls also have a SqlCacheDependency property that should be used if you are using SQL cache dependencies. Also note that while the AccessDataSource has this property, attempting to use it in will result in a NotSupportedException exception to be thrown. Also note that the data source controls will only cache data if EnableCaching is set to True and either a time-based expiry is specified via the CacheDuration property or a SQL cache dependency is specified.

The following declarative syntax shows an AccessDataSource that is configured to support caching for an absolute duration of 30 seconds (also be sure to check out the more in-depth demos available for download at the end of this article):

<asp:AccessDataSource ID="ProductsDataSource" runat="server" 
    DataFile="~/App_Data/Northwind.mdb"
    SelectCommand="SELECT * FROM [Products]"
    CacheDuration="30" 
    EnableCaching="True">
</asp:AccessDataSource>

When this AccessDataSource's Select method was invoked by a data Web control (such as a GridView), the AccessDataSource would first see if its data was in the data cache. If not, it would connect to the Microsoft Access database (Northwind.mdb) and issue the SelectCommand query. It would then cache the results in the data cache and return them to the requesting data Web control. Now, imagine that five seconds later another user visits the page. The data Web control will again request the AccessDataSource for its data, but this time the data will be in the cache. Therefore, the AccessDataSource will return its data to the data Web control without having to connect to the database. After 30 seconds, though, the data will be evicted from the cache and the subsequent request will go back to the database.

A Detailed Look at How the Data Source Caches its Data


When the Select method is invoked for a data source control that has been configured for caching, the data source control starts by checking to see if its data resides in the data cache. As mentioned earlier, the data cache's items are accessed by a string key. The key used by the data source control is a combination of its essential properties. For the SqlDataSource, this includes the value of the CacheDuration, CacheExpirationPolicy, ConnectionString, SelectCommand, and SelectParameters properties. This ensures that the cache is unique per the connection, per the SELECT query, and per the SELECT query's parameter names and values (if any).

If the item is found in the data cache, the data source control returns the cached data and does not raise its Selecting event. As discussed in the Examining the Data Source Control's Events article, the Selecting event fires each time the data source control's Select method is invoked and data is retrieved from the underlying store.

If the item is not found in the cache, then the data source control proceeds through its normal selecting workflow: the Selecting event fires, the underlying data store is accessed and data retrieved, and the Selected event fires. Before the data is returned, however, the data source control first adds it to the data cache, using the same key construction process discussed above.

The following sequence diagram depicts the caching workflow for the ObjectDataSource, although the workflow is identical for the AccessDataSource, SqlDataSource, and XmlDataSource controls as well. Note how the Selecting event does not first if the item is served from the cache.

The workflow of an object data source that uses caching.

We can use the fact that the Selecting event only fires when the data is retrieved from the underlying data store to display information on a page of when the data was last cached. The examples available for download at the end of this article use a Label Web control that's updated with the current date and time each time the Selecting event fires, thereby showing the most recent time the cache was updated. While an end user might not care or need to see this information, it's helpful for page developers as it shows when cached data is being stored and what actions can cause the cached data to be prematurely evicted.

Evicting Items from the Cache


One downside of caching is stale data. While a short time-based expiry can help limit the total duration of potentially stale data, there are other actions that can be taken to forcibly evict an item from the data cache. The data source controls will automatically remove their data from the cache if the data source control's Insert, Update, or Delete methods are invoked. We've yet to explore these data modification methods available in the data source controls, but we most certainly will in a future installment. In short, these methods modify the underlying data store, as their names imply, and can be configured declaratively. When any of these methods are executed, the data source control is modifying the underlying data store, so it makes sense for the data source control to evict the cached data since it now knows that that data is stale. You can see this behavior in the examples available for download at the end of this article.

You can also programmatically remove the data source control's cached data by using the CacheKeyDependency property. Simply set the CacheKeyDependency property to the key value of some data in the cache. Then, to remove the data source control's cached data, simply update the cache item CacheKeyDependency.

Start by setting the data source control's CacheKeyDependency property to the name of the cache item key you want to serve as a dependency. You can choose any old name for this property:

<asp:AccessDataSource ID="ProductsDataSource" runat="server" 
    DataFile="~/App_Data/Northwind.mdb"
    SelectCommand="SELECT * FROM [Products]"
    CacheDuration="30" 
    EnableCaching="True"
    CacheKeyDependency="ProductsDependency">
</asp:AccessDataSource>

Next, it's imperative that this item exists in the cache, otherwise the data cached by the data source control will be immediately evicted from the data cache each time its added. In the Page_Load event handler, test to see if the item exists in the cache and, if not, add it:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
    'Add the Cache item, if needed
    If Cache(ProductsDataSource.CacheKeyDependency) Is Nothing Then
        Cache(ProductsDataSource.CacheKeyDependency) = DateTime.Now
    End If
End Sub

Here I assign DateTime.Now to the cache item, but you can use any value. DateTime.Now is a good choice, though, because it indicates the last time the cache item was last updated.

To programmatically evict the data source's cached data, simply update the value of the Cache(ProductsDataSource.CacheKeyDependency) cache item, such as to the current date and time (Cache(ProductsDataSource.CacheKeyDependency) = DateTime.Now). In the download at the end of this article there's an example that includes a Button Web control that, when clicked, evicts the data from the cache by updating Cache(ProductsDataSource.CacheKeyDependency) to the current date and time. That's all there is to it!

Conclusion


The data source controls make accessing and working with data as easy as setting a few properties. Oftentimes, no code is required. As we saw in this article, this declarative model is also extended to caching. A data source control's data can be cached in the data cache using a time-based expiry simply by setting the EnableCaching property to True and the CacheDuration property to the duration the data should be cached (in seconds). The SqlDataSource and ObjectDataSource controls can also use SQL cache dependencies, although this topic will have to wait for a future article.

Happy Programming!

  • By Scott Mitchell


    Futher Readings:


  • Caching for Performance
  • ASP.NET 2.0 Caching Features (includes SQL cache dependencies)
  • ASP.NET Caching: Techniques and Best Practices
  • A Video on Using Caching in ASP.NET 2.0
  • Attachments:


  • Download the code used in this article

  • Article Information
    Article Title: ASP.NET.Accessing and Updating Data in ASP.NET: Declaratively Caching Data
    Article Author: Scott Mitchell
    Published Date: January 24, 2007
    Article URL: http://www.4GuysFromRolla.com/articles/012407-1.aspx


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