Online Book Reader

Home Category

Programming Microsoft ASP.NET 4 - Dino Esposito [385]

By Root 5423 0
cache dependency object and inherits the base CacheDependency class.

A Cache Dependency for XML Data


Suppose your application gets some key data from a custom XML file and you don’t want to access the file on disk for every request. So you decide to cache the contents of the XML file, but still you’d love to detect changes to the file that occur while the application is up and running. Is this possible? You bet. You arrange a file dependency and you’re done.

In this case, though, any update to the file that modifies the timestamp is perceived as a critical change. As a result, the related entry in the cache is invalidated and you’re left with no choice other than re-reading the XML data from the disk. The rub here is that you are forced to re-read everything even if the change is limited to a comment or to a node that is not relevant to your application.

Because you want the cached data to be invalidated only when certain nodes change, you create a made-to-measure cache dependency class to monitor the return value of a given XPath expression on an XML file.

Note

If the target data source provides you with a built-in and totally asynchronous notification mechanism (such as the command notification mechanism of SQL Server), you just use it. Otherwise, to detect changes in the monitored data source, you can only poll the resource at a reasonable rate.

Designing the XmlDataCacheDependency Class


To better understand the concept of custom dependencies, think of the following example. You need to cache the inner text of a particular node in an XML file. You can define a custom dependency class that caches the current value upon instantiation and reads the file periodically to detect changes. When a change is detected, the cached item bound to the dependency is invalidated.

Note

Admittedly, polling might not be the right approach for this particular problem. Later on, in fact, I’ll briefly discuss a more effective implementation. Be aware, though, that polling is a valid and common technique for custom cache dependencies.

A good way to poll a local or remote resource is through a timer callback. Let’s break the procedure into a few steps:

The custom XmlDataCacheDependency class gets ready for the overall functionality. It initializes some internal properties and caches the polling rate, file name, and XPath expression to find the subtree to monitor.

After initialization, the dependency object sets up a timer callback to access the file periodically and check contents.

In the callback, the return value of the XPath expression is compared to the previously stored value. If the two values differ, the linked cache item is promptly invalidated.

There’s no need for the developer to specify details about how the cache dependency is broken or set up. The CacheDependency class takes care of it entirely.

Note

If you’re curious to know how the Cache detects when a dependency is broken, read on. When an item bound to a custom dependency object is added to the Cache, an additional entry is created and linked to the initial item. NotifyDependencyChanged simply invalidates this additional element which, in turn, invalidates the original cache item.

Implementing the Dependency


The following source code shows the core implementation of the custom XmlDataCacheDependency class:

public class XmlDataCacheDependency : CacheDependency

{

// Internal members

static Timer _timer;

Int32 _pollSecs = 10;

String _fileName;

String _xpathExpression;

String _currentValue;

public XmlDataCacheDependency(String file, String xpath, Int32 pollTime)

{

// Set internal members

_fileName = file;

_xpathExpression = xpath;

_pollSecs = pollTime;

// Get the current value

_currentValue = CheckFile();

// Set the timer

if (_timer == null) {

var ms = _pollSecs * 1000;

var cb = new TimerCallback(XmlDataCallback);

_timer = new Timer(cb, this, ms, ms);

}

}

public String CurrentValue

{

get { return _currentValue; }

}

public void XmlDataCallback(Object sender)

{

// Get a reference to THIS dependency

Return Main Page Previous Page Next Page

®Online Book Reader