Understand SQL Cache Notifications

Cache Notifications in SQL Server 2000 or SQL Server 7
ASP.NET uses a polling model for SQL Server 2000 and SQL Server 7. Older versions of SQL Server
and other databases aren’t supported (although third parties can implement their own solutions by
creating a custom dependency class).
With the polling model, ASP.NET keeps a connection open to the database and uses a dedicated
thread to check periodically if a table has been updated. The effect of tying up one connection
in this way isn’t terribly significant, but the extra database work involved with polling does add
some database overhead. For the polling model to be effective, the polling process needs to be
quicker and lighter than the original query that extracts the data.
Enabling Notifications
Before you can use SQL Server cache invalidation, you need to enable notifications for the database.
This task is performed with the aspnet_regsql.exe command-line utility, which is located in the
c:\[WinDir]\Microsoft.NET\Framework\[Version] directory. To enable notifications, you need to
use the -ed command-line switch. You also need to identify the server (use -E for a trusted connection
and -S to choose a server other than the current computer) and the database (use -d). Here’s an
example that enables notifications for the Northwind database on the current server:
aspnet_regsql -ed -E -d AspNet

Employees table. To check for changes that might invalidate
your cached object, you need to know if any record in the Employees table is inserted, deleted,
or updated. You can watch for these operations using triggers. For example, here’s the trigger on the
Employees table that aspnet_regsql creates:
CREATE TRIGGER dbo.[Employees_AspNet_SqlCacheNotification_Trigger]
ON [Employees]
FOR INSERT, UPDATE, DELETE AS BEGIN
SET NOCOUNT ON
EXEC dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure N'Employees'
END
The AspNet_SqlCacheUpdateChangeIdStoredProcedure stored procedure simply increments
the changeId for the table:
CREATE PROCEDURE dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure
@tableName NVARCHAR(450)
AS
BEGIN
UPDATE dbo.AspNet_SqlCacheTablesForChangeNotification WITH (ROWLOCK)
SET changeId = changeId + 1
WHERE tableName = @tableName
END
GO
The AspNet_SqlCacheTablesForChangeNotification contains a single record for every table
you’re monitoring. As you can see, when you make a change in the table (such as inserting a
record), the changeId column is incremented by 1. ASP.NET queries this table repeatedly and keeps
track of the most recent changeId values for every table. When this value changes in a subsequent
read, ASP.NET knows that the table has changed.
This hints at one of the major limitations of cache invalidation as implemented in SQL Server
2000 and SQL Server 7. Any change to the table is deemed to invalidate any query for that table. In
other words, if you use this query:
SELECT * FROM Employees WHERE City='London'
the caching still works in the same way. That means if any employee record is touched, even if the
employee resides in another city (and therefore isn’t one of the cached records), the notification is
still sent and the cached item is considered invalid. Keeping track of what changes do and do not
invalidate a cached data object is simply too much work for SQL Server 2000 (although it is possible
in SQL Server 2005).


Enabling ASP.NET Polling
The next step is to instruct ASP.NET to poll the database. You do this on a per-application basis. In
other words, every application that uses cache invalidation will hold a separate connection and poll
the notification table on its own.
To enable the polling service, you use the <sqlCacheDepency> element in the web.config file.
You set the enabled attribute to true to turn it on, and you set the pollTime attribute to the number
of milliseconds between each poll. (The higher the poll time, the longer the potential delay before a
change is detected.) You also need to supply the connection string information.
For example, this web.config file checks for updated notification information every 15 seconds:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<connectionStrings>
<add name="Northwind" connectionString=
"Data Source=localhost;Initial Catalog=Northwind;Integrated Security=SSPI"/>
</connectionStrings>
<system.web>
<caching>
<sqlCacheDependency enabled="true" pollTime="15000" >
<databases>
<add name="Northwind" connectionStringName="Northwind" />
</databases>
</sqlCacheDependency>
</caching>
...
</system.web>
</configuration>
Creating the Cache Dependency
Now that you’ve seen how to set up your database to support SQL Server notifications, the only
remaining detail is the code, which is quite straightforward. You can use your cache dependency
with programmatic data caching, a data source control, and output caching.
For programmatic data caching, you need to create a new SqlCacheDependency and supply
that to the Cache.Insert() method, much as you did with file dependencies. In the SqlCache-
Dependency constructor, you supply two strings. The first is the name of the database you defined
in the <add> element in the <sqlCacheDependency> section of the web.config file. The second is
the name of the linked table.
Here’s an example:
// Create a dependency for the Employees table.
SqlCacheDependency empDependency = new SqlCacheDependency(
"Northwind", "Employees");


// Add a cache item that will be invalidated if this table changes.
Cache.Insert("Employees", dsEmployees, empDependency);
To perform the same trick with output caching, you simply need to set the SqlCache-
Dependency property with the database dependency name and the table name, separated
by a colon:
<%@ OutputCache Duration="600" SqlDependency="Northwind:Employees"
VaryByParam="none" %>
You can also set the dependency using programmatic output caching with the Response.Add-
CacheDependency() method:
Response.AddCacheDependency(empDependency)
// Use output caching for this page (for 60 seconds or until the table changes).
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetValidUntilExpires(true);
Finally, the same technique works with the SqlDataSource and ObjectDataSource controls:
<asp:SqlDataSource EnableCaching="True"
SqlCacheDependency="Northwind:Employees" ... />
posted @ 2008-04-08 22:58  陋室  阅读(460)  评论(0编辑  收藏  举报