Advanced ASP.NET : Caching with Dependencies

2/19/2011 4:26:55 PM
As time passes, the information in your data source may change. If your code uses caching, you may remain unaware of the changes and continue using out-of-date information from the cache. To help mitigate this problem, ASP.NET supports cache dependencies. Cache dependencies allow you to make a cached item dependent on another resource, so that when that resource changes, the cached item is removed automatically.

ASP.NET includes three types of dependencies:

  • Dependencies on files or folders

  • Dependencies on other cached items

  • Dependencies on a database query

You'll see all these types of dependencies in the following section.

1. File Dependencies

To use a cache dependency, you need to create a CacheDependency object. You then need to supply the CacheDependency object when you add the dependent cached item.

For example, the following code creates a CacheDependency that depends on an XML file named ProductList.xml. When the XML file is changed, the CacheDependency will be invalidated, and the dependent cached item will be evicted from the cache immediately.

' Create a dependency for the ProductList.xml file.
Dim prodDependency As New CacheDependency( _

' Add a cache item that will be dependent on this file.
Cache.Insert("ProductInfo", prodInfo, prodDependency)

Monitoring begins as soon as the CacheDependency object is created. If the XML file changes before you have added the dependent item to the cache, the item will expire immediately as soon as it's added.

Figure 1 shows a simple test page that is included with the samples for thisarticle . It sets up a dependency, modifies the file, and allows you to verify that the cached item has been dropped from the cache.

Figure 1. Testing cache dependencies

The CacheDependency object provides several constructors. You've already seen how it can make a dependency based on a file by using the file name constructor. You can also specify a directory that needs to be monitored for changes, or you can use a constructor that accepts an array of strings that represent multiple files and directories.

2. Cache Item Dependencies

The CacheDependency class provides another constructor that accepts an array of file names and an array of cache keys. Using the array of cache keys, you can create a cached item that's dependent on another item in the cache. (If you don't want to use file dependencies at all, you simply supply a null reference (Nothing) for the first parameter.)

Here's an example that makes one item dependent on another cached item, without using file dependencies:

Cache("Key1") = "Cache Item 1"

' Make Cache("Key2") dependent on Cache("Key1").
Dim dependencyKey(0) As String
dependencyKey(0) = "Key1"
Dim dependency As New CacheDependency(Nothing, dependencyKey)

Cache.Insert("Key2", "Cache Item 2", dependency)

Now, when the first cached item changes or is removed from the cache, the second cached item will automatically be dropped from the cache as well.

3. SQL Server Cache Dependencies

A more complex kind of cache dependency is the SQL Server cache dependency. In a nutshell, SQL cache dependencies provide the ability to automatically invalidate a cached data object (such as a DataSet) when the related data is modified in the database.

Although this feature is technically supported in SQL Server 2000, it's a better idea to use SQL Server 2005 or later. That's because these versions of SQL Server have a built-in notification system, which makes tasks like these much more efficient.

To understand how database dependencies work, you first need to know a bit about SQL Server's built-in messaging system, which is called the Service Broker. The Service Broker manages queues, which are database objects that have the same standing as tables, stored procedures, or views.

Thanks to queues, you can instruct SQL Server to send notifications for specific events using the CREATE EVENT NOTIFICATION command. But ASP.NET offers a more convenient, higher-level model—you register a query, and ASP.NET automatically instructs SQL Server to send notifications for any operations that would affect the results of that query. Every time you perform an operation, SQL Server determines whether your operation affects a registered command. If it does, SQL Server sends a notification message and stops the notification process. Figure 2 shows an overview of how this cache invalidation system works.

Figure 2. Monitoring a database for changes in SQL Server

Notifications work with SELECT queries and stored procedures. However, some restrictions exist for the SELECT syntax you can use. To properly support notifications, your command must adhere to the following rules:

  • You must fully qualify table names in the form [Owner].table, as in dbo.Employees (not just Employees).

  • Your query cannot use an aggregate function, such as COUNT(), MAX(), MIN(), or AVERAGE().

  • You cannot select all columns with the wildcard * (as in SELECT * FROM Employees). Instead, you must specifically name each column so that SQL Server can properly track changes that do and do not affect the results of your query.

Here's an acceptable command:

SELECT EmployeeID, FirstName, LastName, City FROM dbo.Employees

These are the most important rules, but the SQL Server Books Online has a lengthy list of caveats and exceptions. If you break one of these rules, you won't receive an error. However, the notification message will be sent as soon as you register the command, and the cached item will be invalidated immediately.

3.1. Enabling the Service Broker

SQL Server is often installed with carefully locked-down settings for optimum security. To use SQL Server notifications, you may have to enable features that are currently switched off.

First, you need to enable the Service Broker, which watches for changes in the database and delivers the notifications to the appropriate queue. The Service Broker must be specifically enabled for each database that you want to use with cache dependencies.

If the Service Broker isn't currently enabled for your database (or if you're just not sure), there's an easy solution. First, launch the Visual Studio 2010 Command Prompt window (click the Start button and choose All Programs => Microsoft Visual Studio 2010 => Visual Studio Tools => Visual Studio Command Prompt). Then, run the SqlCmd.exe command-line utility, specifying the –S parameter and the name of your server. Here's an example:

SqlCmd -S localhost\SQLEXPRESS

This connects to SQL Server Express on the current computer. If you're using the full version of SQL Server, you won't need to supply the instance name (you can use just localhost instead of localhost\SQLEXPRESS). If your database is installed on another server, use its computer name instead of localhost.

The SqlCmd.exe utility provides a command prompt where you can enter SQL commands. Use it to enter the following SQL statements:

USE Northwind

Of course, if you want to enable the Service Broker for a different database (other than Northwind), you can modify this SQL accordingly. You can enable the Service Broker for as many databases as you'd like.

Once you're finished, type quit to exit the SqlCmd tool.

3.2. Initializing the Caching Service

Before you can use SQL cache dependencies with SQL Server, you need to call the shared SqlDependency.Start() method. This initializes the listening service on the web server.

Dim connectionString As String = _

You need to call the Start() method only once over the lifetime of your web application, so it often makes sense to place the call in the Application_Start() method of the global.asax file so it's triggered automatically. It's safe to call the Start() method even if the listener is already started, as this won't cause an error. You can also use the Stop() method to halt the listener.

3.3. Creating the Cache Dependency

When you create the dependency object, you need to supply the command that you're using to retrieve your data. That way, SQL Server knows what range of records you want to monitor.

To specify the command, you create the SqlCacheDependency using the constructor that accepts a SqlCommand object. Here's an example:

' Create the ADO.NET objects.
Dim con As New SqlConnection(connectionString)
Dim query As String = _
"SELECT EmployeeID, FirstName, LastName, City FROM dbo.Employees"
Dim cmd As New SqlCommand(query, con)
Dim adapter As New SqlDataAdapter(cmd)

' Fill the DataSet.
Dim ds As New DataSet()
adapter.Fill(ds, "Employees")

' Create the dependency.
Dim empDependency As New SqlCacheDependency(cmd)

' Add a cache item that will be invalidated if one of its records changes
' (or a new record is added in the same range).
Cache.Insert("Employees", ds, empDependency)

Now, when you change the data in the table, the notification will be delivered, and the item will be removed from the cache. The next time you create the DataSet, you'll need to add it back to the cache with a new SqlCacheDependency.


If your cached item never expires, the ASP.NET polling service is not receiving the invalidation message. This has several possible causes. The most common is that your database server doesn't have the common language runtime enabled. The procedure that sends notification messages is a .NET procedure, so it requires this support.

To enable CLR support, fire up the Visual Studio Command Prompt window, and run the SqlCmd.exe command-line utility. Here's how to do it for SQL Server Express:

SqlCmd -S localhost\SQLEXPRESS

Now enter the following SQL statements:

EXEC sp_configure 'show advanced options', '1'
EXEC sp_configure 'clr enabled', 1

Then type quit to exit the SqlCmd tool.

On the other hand, if your cached item expires immediately, the most likely problem is that you've broken one of the rules for writing commands that work with notifications, as described earlier.

PS4 game trailer XBox One game trailer
WiiU game trailer 3ds game trailer
Top 10 Video Game
-   Minecraft Mods - MAD PACK #10 'NETHER DOOM!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Minecraft Mods - MAD PACK #9 'KING SLIME!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Minecraft Mods - MAD PACK #2 'LAVA LOBBERS!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Minecraft Mods - MAD PACK #3 'OBSIDIAN LONGSWORD!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Total War: Warhammer [PC] Demigryph Trailer
-   Minecraft | MINIONS MOVIE MOD! (Despicable Me, Minions Movie)
-   Minecraft | Crazy Craft 3.0 - Ep 3! "TITANS ATTACK"
-   Minecraft | Crazy Craft 3.0 - Ep 2! "THIEVING FROM THE CRAZIES"
-   Minecraft | MORPH HIDE AND SEEK - Minions Despicable Me Mod
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 92 "IS JOE DEAD?!"
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 93 "JEDI STRIKE BACK"
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 94 "TATOOINE PLANET DESTRUCTION"
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 95 "TATOOINE CAPTIVES"
-   Hitman [PS4/XOne/PC] Alpha Gameplay Trailer
-   Satellite Reign [PC] Release Date Trailer
Game of War | Kate Upton Commercial