search
Japanese Chinese Nederlands Espanol Italiano Deutsch Francais Twitter Rss Feeds
MicrosoftArticlesForumsFAQs
C# .NET
VB.NET
Visual Studio .NET
ADO.NET
Xml / Xslt
VB 6.0
.NET CF
GDI+
LINQ
Deployment
Security
FoxPro
Silverlight / WPF
Entity Framework
RIA Services

Web ProgrammingArticlesForumsFAQs
JavaScript
ASP
ASP.NET
Web Services

Non-MicrosoftArticlesForumsFAQs
NHibernate
Perl
PHP
Ruby
Java
Linux / Unix
Apple
Open Source

DatabasesArticlesForumsFAQs
SQL Server
Access
Oracle
MySQL
Other Databases

OfficeArticlesForumsFAQs
Excel
Word
Powerpoint
Outlook
Publisher
Money

Operating SystemsArticlesForumsFAQs
Windows 7
Windows Server
Windows Vista
Windows XP
Windows Update
MAC
Linux / UNIX

Server PlatformsArticlesForumsFAQs
BizTalk
Site Server
Exhange Server
IIS

Graphic DesignArticlesForumsFAQs
Macromedia Flash
Adobe PhotoShop
Expression Blend
Expression Design
Expression Web

OtherArticlesForumsFAQs
Subversion / CVS
Ask Dr. Dotnetsky
Active Directory
Networking
Uninstall Virus
Job Openings
Product Reviews
Search Engines
Resumes

 

Caching Pages and Application Data with Database Dependencies


By Peter Bromberg
Printer Friendly Version
View My Articles
26 Views
    

Overview of the steps necessary to cache Pages or application data based on the new ASP.NET 2.0 SqlCacheDependency features.


There is nothing more dreadful than imagination without taste.  - Goethe


In a previous article, I covered much of the basics of ASP.NET caching. Here I'll narrow the focus on to two specific implementations of caching -- for both ASP.NET Pages and Application Data -- using Database Dependencies.

Most ASP.NET developers get involved with caching as an afterthought, usually implementing some sort of caching only after their web application is completed. I suggest very strongly that this approach is both wrong and flawed. When you start to design an ASP.NET application and you are grappling with how to retrieve and use any kind of object (database data, a page, a control, or other objects) that is expensive to create, the very first thing on your mind should be, "How can I cache this to speed up operations?". Engineer caching into your apps from the very beginning.

I was aware of caching capabilities very early on in the history of ASP.NET, but I didn't really "get the message" as I've described just above until I sat in one of Rob Howard's ASP.NET presentations at Tech-Ed 2004. Rob demonstrated some advanced caching techniques (including one I've adapted for the SQLite database here) and showed real-time App Center Test results, both with and without caching. When you are in a room full of 600 other goons all of whom are having an epiphany at the same time, the message really sinks in. I hope this article helps to get it across for you, too, or at least helps to motivate further study.

"Caching" is a somewhat ambiguous term in that it doesn't always mean using the ASP.NET Cache class. To me, what caching really means is the ability to store expensive-to-create objects or data, and produce them (or their results) on demand without having to recreate the data. The ADO.NET SqlConnection Pool is an example of caching database connections, but it does not use the ASP.NET Caching classes. The use of WeakReferences is another, for caching expensive objects.

Caching is kind of like a hybrid car, having a set of batteries charged up with exactly what you need, that can deliver your power on demand without having to start the expensive gasoline engine. If the batteries are low or empty, the gas engine starts on demand and not only provides your power, it also recharges the batteries so that you can have more efficient throughput. Caching data for as little as 1 second can have a major effect on site performance, as Rob has so astutely pointed out in his Tech-Ed and other presentations.

In ASP.NET 2.0, the caching infrastructure you have to work with has been appropriately "souped up" to provide lots more flexibility and ease of use. You can cache pages ( <%@ OuptputCache Duration="10" VaryByParam="None" %> ), pages based on Query String or FormField parameters, pages based on browser type and / or version, or even by custom developer-defined strings. You can also cache pages based on database dependencies, and that's what we will examine here.

ASP.NET 1.1 offered a number of ways to cache data with dependencies, but using database dependencies wasn't one of them. In ASP.NET 2.0, we can cache pages based on data in a SQL Server database. This includes SQL Server 7.0, 2000, 2005, MSDE, and SQLExpress.

As with most other cache dependencies, the controlling factor is to be able to determine that cache content should be expired based on the knowledge that some data has changed -- in this case, data in the database.

Caching Pages with SqlDependencies

SQL Server 2005 and Express offer built-in notification events, and neither requires any configuration changes to support this other than adding the <sqlCacheDependency> element to the web.config file. With SQL Server 7.0, 2000 and MSDE, the ability to determine if data has changed is provided via a polling mechanism. The table AspNet_SqlCacheTablesForChangeNotification contains a row for each table to be monitored. When data in a monitored table changes, a trigger changes the value in the changeId column for that table and the next polling interval picks this up. With these older databases, your database needs to be altered to support these changes.

There are two options for doing this:

1) aspnet_regsql.exe can be run to configure a database for notifications, and to configure a specific table to be monitored:

Database: aspnet_regsql -S <server> -E -d <database> -ed
Table:      aspnet_regsql -S <server> -E -d <database> -et -t <table>

2) Using the SqlCacheDependencyAdmin Class.

Simplified Example:

Database: SqlCacheDependencyAdmin.EnableNotifications(connectionString);
Table:       SqlCacheDependencyAdmin.EnableNotifications(connectionString, tableName);

There are corresponding Disable methods as well.

When your database is configured for notifications, you add the <sqlCacheDependency> element to your web.config:

<caching>
<sqlCacheDependency enabled="true" pollTime="30000">
<databases>
<add name="Pubs" connectionStringName="PubsConn" pollTime="20000" />
</databases>
</sqlCacheDependency>
</caching>

Note that you can override the default pollTime attribute for a specific connectionString in the databases node. The pollTime attribute is in milliseconds. The name attribute of the <add> element in the <databases> element defines the name of the database when defining SqlDependencies in your app; it does not have to be the actual database name. The connectionStringName attribute must be set to the name of a connection string stored in the <connectionStrings> element of your web.config.

With your setup complete, you can cache any page based on a database dependency by adding the <@OutputCache page directive, like so:

<%@ OutputCache Duration="100" VaryByParam="none" SqlDependency="Pubs:Books" %>

The SqlDependency attribute is set to the name of the database as defined in web.config "name" attribute, followed by a colon and the name of the table that you want to use as the dependency for the page. Multiple databases and tables can be specified by providing a semicolon-delimited list of database:table pairs.

Caching Application Data with SqlDependencies.

You do not have to cache the entire page with SqlDependencies. You can cache individual controls, or where appropriate, the application data that is used by a control (or the page).

To cache Application Data, you would configure your SQL Server database as described above, and add the <sqlCacheDependency> element to your web.config the same way as for Page caching.

Once you've configured your SQL Server and sqlCacheDependency web.config element, adding data to the ASP.NET Cache with a SqlCacheDependency is simple. You only need to create an instance of a SqlCacheDependency class, specifiying the database (as in the web.config element) and the table, and pass this instance when adding your data to the Cache:

SqlCacheDependency sqlDep =new SqlCacheDependency("Pubs", "Books");
Context.Cache.Insert("myCacheKey", dataSetBookData, sqlDep);

If you are using SQL Server 2005 or Express, you can create a SqlCacheDependency object by passing a SqlCommand object to the constructor. This provides a more granular approach to define the data being monitored and used for expiring the data from the Cache, because a SqlCommand can contain any stored procedure invocation or CommandText including a WHERE clause. For example, "newest employees":

cmdText = "SELECT FIRSTNAME, LASTNAME, EMPLOYEEID FROM EMPLOYEES WHERE HIREDATE >'09/30/2006'" ;
sqlCommand sqlCmd = new SqlCommand(cmdText, sqlConnection);
SqlCacheDependency sqlDep = new SqlCacheDependency(sqlCmd);
// etc.

The above examples are all quite simplified and do not have any exception handling, which of course, I leave to the expert reader to supply.

Caching DataSources

Finally, you can cache datasources. The XmlDataSource, ObjectDataSource and SqlDataSource classes all offer caching:

dataSource.EnableCaching=true;
dataSource.CacheDuration=5;

Summary

The SqlCacheDependency and related tools are an important tool in your arsenal of techniques to be a more professional ASP.NET developer. Developers should strive to create a mindset that includes using caching, optionally with the SqlCacheDependency tools, from the outset when developing ASP.NET 2.0 applications. The result will not only be more scalable web applications, but the recognition of your peers and the customers who consume your work.


Biography - Peter Bromberg
Peter Bromberg is a C# MVP, MCP, and .NET expert who has worked in banking, financial and telephony for over 20 years. Pete focuses exclusively on the .NET Platform, and currently develops SOA and other .NET applications for a Fortune 500 clientele. Peter enjoys producing digital photo collage with Maya,playing jazz flute, the beach, and fine wines. You can view Peter's UnBlog and IttyUrl sites.
Please post questions at forums, not via email!

button
Article Discussion: Caching Pages and Application Data with Database Dependencies
Peter Bromberg posted at Sunday, September 24, 2006 9:17 AM
Original Article
 

SQL 2005
Daniel Plomp replied to Peter Bromberg at Tuesday, October 17, 2006 2:57 AM

Hello Peter,

Nice to read your article about caching. I've one question about it, if you don't mind.

I use a SQL Server 2005 (Developer and Standard in production). I read a lot of articles that where saying you can enable the Notification Service in SQL Server 2005 and then the only thing you should do on e.g. the ObjectDataSource is set Caching = True and use 'CommandNotification' in the SqlCacheDependency property.

For some reason I didn't get this to work. I'm really looking for a good article on how to enable this.

On the other hand, I also read that you should only use Notification Services if the data doesn't change very often. So, lots of theories.

What would be the best way to cache DataSourceObjects and how can I see if it is really working?

Daniel

 

ObjectDataSource Control
mike sus replied to Peter Bromberg at Thursday, December 14, 2006 7:13 PM
Peter,

How would you implement caching for an OjbectDataSource Control where a datatable is returned from a BLL or DAL layer? I'd like to be able to use the native sorting and paging, but not round trip back to the database is certain instances.

Thanks,

Mike
 

It doesn't matter "where" the Data is coming from.
Peter Bromberg replied to mike sus at Thursday, December 14, 2006 8:52 PM
If you turn on caching by virtue of the ODS control, you'll get caching.