Skip navigation.

New Font On the BlockAll recent postsThe Purpose and Objectives of a Business

Overview of Sql Cache Dependency

Database cache dependency must’ve been among the most anticipated additions in ASP.NET 2.0. Caching, in general, calls for some tough decisions. How long to cache data for? Can we afford to present stale data to the user by way of caching? What kind of data are we dealing with and can we even afford it to be stale? How do we invalidate the cache once the data source changes? and so on.

Sql cache dependency allows to simplify this decision-making process. In a nutshell, with the SqlCacheDependency class you can cache some data and make its expiration (invalidation) dependent on changes (updates, deletes, inserts) in a particular table.

Last year I wrote something similar for 1.x (see Lightweight Database Cache Dependencies part 1 and part 2). I know Jon Galloway took a stab at it too. I’ve seen many other people devise something along these lines, which clearly shows this feature was begging to be introduced.

Configuring SQL Cache Dependency (Sql Server 7 and 2000)

There’s some manual configuration of web.config required to specify which connection string to use, how often to poll the database for changes, etc. You can set up more than one database connection and poll several databases—all from the same web application!

You also need to “enable a database for SQL cache dependency” by running Aspnet_regsql.exe. Pay attention to the -ed (enable database), -t (table) and -et (enable table) switches.

For example, to enable a cache dependency on a particular database, run this command:

aspnet_regsql.exe -S server -U user -P password -d database -ed

This creates a new table, AspNet_SqlCacheTablesForChangeNotification, in the designated database. Next, several AspNet_SqlCacheXxxx stored procs are created in the same database.

The way SqlCacheDependency works is it ties a cached item to a table. Therefore you need to decide which tables to poll for changes in the first place. You “enlist” tables by running aspnet_regsql.exe again:

aspnet_regsql.exe -S server -U user - P password -d database -t table -et

Once you run this command, the specified table name is added to AspNet_SqlCacheTablesForChangeNotification. Also, a trigger is set up on your table. Any time an update, delete or insert takes place, a “change counter” is incremented in AspNet_SqlCacheTablesForChangeNotification, and any data, cached with a dependency on this table, is flushed within the polling interval.

Getting Permissions Right

Rigt off the bat, I was greeted with a stored proc permissioning error. Whenever we create a database, we assign it its own login with the bare minimum of permissions (read more)—db_datareader and db_datawriter.

If any of the AspNet_SqlCacheXxxx stored procs gives you grief, try this:

GRANT EXECUTE ON dbo.AspNet_SqlCacheXxxx TO public

Multiple Table Dependencies

It’s not immediately obvious how to tie cached data to multiple tables. I doubt there are too many applications where data is fetched strictly via single-table SELECT statements, so a more realistic scenario is to have data whose “freshness” depends on changes in several tables.

Luckily, there’s another new class, AggregateCacheDependency, which comes to the rescue:

The AggregateCacheDependency class monitors a collection of dependency objects so that when any of them change, the cached item is automatically removed. The objects in the array can be CacheDependency objects, SqlCacheDependency objects, custom objects derived from CacheDependency, or any combination of these.

The AggregateCacheDependency class differs from the CacheDependency class in that it allows you to associate multiple dependencies of different types with a single cached item.

Consider this C# snippet:

SqlCacheDependency 
   dep1 = new SqlCacheDependency ("MyDb", "Users"),
   dep2 = new SqlCacheDependency ("MyDb", "UserRoles"),
   dep3 = new SqlCacheDependency ("MyDb", "Policies");

AggregateCacheDependency aggDep = new AggregateCacheDependency ();
aggDep.Add (dep1, dep2, dep3);

Cache.Insert ("SomeKey", someData, aggDep);

There are dependencies on tables Users, UserRoles and Policies, all tied together by an aggregate cache dependency. Anything changes in one of these tables—the cached item is invalidated, and it’s time to bring in and cache fresh data.

Conclusion

As with any caching approach, you win some and you lose some. The jury is still out on performance of Sql cache dependency. I don’t know if having a trigger on every monitored table is a good thing or a bad thing, but change detection boils down to a simple database read, and it doesn’t get much simpler than that.

The discussion above is limited to Sql Server 7 and 2000, which have only the polling mode of change detection available. I haven’t had a chance to play with the Sql Server 2005 notification-based cache invalidation, but it looks very promising.

Comments

Comment permalink 1 Charlie |
I'm new to SqlCacheDependency. Do I need to do this:
aspnet_regsql.exe -S server -U user - P password -d database -t table -et

And:




connectionStringName="Northwind"
pollTime="1000"/>





if I'm using SQL Server 2005?
Comment permalink 2 ravi |
How can I clear these AggregateCacheDependency objects from my application.

Though my site is working faster with this, SQL is logging many query notifications and at times it is giving out of memory exception.

Please tell me when the SQLCacheDependency objects gets cleared from the memory
Comment permalink 3 Milan Negovan |
The aggregate is released from memory when at least one of the monitored tables changes.
Comment permalink 4 Debasish Pramanik |
I have done everything from setting appropriate permissions to what you have mentioned but my cache manager doesn't appropriately. I have developed a winForm app where I get the change notification but for the ASP.NET it doesn't work. Is there palce where there is step by step to make ASP.NET-SQL Server 2005 run on CacheDependency....
Comment permalink 5 Milan Negovan |
If you did everything that's outlined in this post, I can't really tell what's missing. :(
Comment permalink 6 Tanya |
Hi,
How do you set up SqlCacheDependency where webserver and database servers are two different machines? We use Windows authentication between webserver and database server and identity impersonation. It is not clear for me how do I need to run this tool (on which machine and under which login) and how the webserver will be accessing the database server to check for database changes in this case. If somebody can share the knowledge, I'd greatly appreciate.

Thanks,
Tanya
Tanya
Comment permalink 7 Milan Negovan |
Tanya, you can run the command line from any machine as long as you point it to the dB server (the -S switch).

Next, you need to add a system.web | caching | sqlCacheDependency config section in web.config which tells the web server which db connection to use to poll for changes.
Comment permalink 8 Tanya |
Thank you Milan,
What I did is I ran the tool on my local machine and then copied the table and the stored procedures, which were created by the tool, to the testing db server.
Then I ran the stored procedure, which creates a trigger and a row, indicating which table to monitor for changes, in the sqlCacheDependency table and set execute permissions to the sqlCacheDependency role. Basically, I manually recreated everything (I could find the tool has created on my development server) on the testing db server. I also created the settings in the web.config. Now I am getting the error telling me that login is denied for the user ‘’ (empty string) for sqlCacheDependency polling. I am wondering, how I tell both machines which user to use for the sqlCacheDependency polling. Do you know? Thank you,
Tanya
Comment permalink 9 DotNetGuts |
This article was helpful.
Thanks
Comment permalink 10 Sharma |
Hi,

Can I sql server cache database same as my production database.
Please advise.

Emails and Notifications

Would you like to be notified when somebody responds to this post?  Would you like to have these comments emailed to you?

Submit your comment

Please enter only text since all HTML tags except hyperlinks will be stripped. Hyperlinks will become live links. Any comments with flaming or offensive language will be deleted. Be courteous to other posters. Thank you.

Your name (required):
Your email (optional):
Your site's URL (optional):
Enter this number
Type in the number above:
Comment (required):