Looking at SQL Server 2000 Now that the Northwind database and the Customers and Products tables have all been enabled for SQL cache invalidation, look at what has happened in SQL Server
Trang 1Go ahead and enable both the Customers and Product tables You run the command once per table After
a table is successfully enabled, you receive the following response:
Enabling the table for SQL cache dependency
Finished
After the table is enabled, you can begin using the SQL cache invalidation features However, before you
do, the following section shows you what happens to SQL Server when you enable these features
Looking at SQL Server 2000
Now that the Northwind database and the Customers and Products tables have all been enabled for SQL cache invalidation, look at what has happened in SQL Server If you open up the SQL Server Enterprise Manager, you see a new table contained within the Northwind database — AspNet_SqlCacheTablesFor-ChangeNotification(whew, that’s a long one!) Your screen should look like Figure 23-4 Note that SQL
Server 2000 isn’t supported on Vista, so this is a screenshot of a remote SQL 2000 machine viewed from
the SQL Management Studio running on Vista
Figure 23-4
At the top of the list of tables in the right-hand pane, you see the
AspNet_SqlCacheTablesForChange-Notificationtable This is the table that ASP.NET uses to learn which tables are being monitored for
Trang 2change notification and also to make note of any changes to the tables being monitored The table is
actually quite simple when you look at the details, as illustrated in Figure 23-5
Figure 23-5
In this figure, you can see three columns in this new table The first is thetableNamecolumn This column
simply shows aStringreference to the names of the tables contained in the same database Any table
named here is enabled for SQL cache invalidation
The second column,notificationCreated, shows the date and time when the table was enabled for
SQL cache invalidation The final column,changeId, is used to communicate to ASP.NET any changes to
the included tables ASP.NET monitors this column for changes and, depending on the value, either uses
what is stored in memory or makes a new database query
Looking at the Tables That Are Enabled
Using theaspnet_regsql.exetool, you can see (by using a simple command) which tables are enabled
in a particular database If you are working through the preceding examples, you see that so far you have
enabled the Customers and Products tables of the Northwind database To get a list of the tables that are
enabled, use something similar to the following command:
aspnet_regsql.exe -S localhost -U sa -P password -d Northwind -lt
The-ltcommand produces a simple list of tables enabled for SQL cache invalidation Inputting this
command produces the following results:
Listing all tables enabled for SQL cache dependency:
Customers
Products
Disabling a Table for SQL Server Cache Invalidation
Now that you know how to enable your SQL Server database for SQL Server cache invalidation, take a
look at how you remove the capability for a specific table to be monitored for this process To remove a
table from the SQL Server cache invalidation process, use the-dtcommand
In the preceding example, using the-ltcommand showed that you have both the Customers and
Prod-ucts tables enabled Next, you remove the ProdProd-ucts table from the process using the following command:
aspnet_regsql.exe -S localhost -U sa -P password -d Northwind -t Products –dt
Trang 3You can see that all you do is specify the name of the table using the-tcommand followed by a-dt
command (disable table) The command line for disabling table caching will again list the tables that
are enabled for SQL Server cache invalidation; this time, the Products table is not listed — instead, Cus-tomers, the only enabled table, is listed
Disabling a Database for SQL Server Cache Invalidation
Not only can you pick and choose the tables that you want to remove from the process, but you can also disable the entire database for SQL Server cache invalidation In order to disable an entire database, you use the-ddcommand (disable database)
Note that disabling an entire database for SQL Server cache invalidation also means that every single
table contained within this database is also disabled.
This example shows the Northwind database being disabled on my computer:
C:\>aspnet_regsql -S localhost -U sa -P wrox -d Northwind -dd
Disabling the database for SQL cache dependency
Finished
To ensure that the table is no longer enabled for SQL Server cache invalidation, we attempted to list the tables that were enabled for cache invalidation using the-ltcommand We received the following error:
C:\ >aspnet_regsql -S localhost -U sa -P wrox -d Northwind -lt
An error has happened Details of the exception:
The database is not enabled for SQL cache notification To enable a database for
SQL cache notification, please use SQLCacheDependencyAdmin.EnableNotifications
method, or the command line tool aspnet_regsql.exe
If you now open the Northwind database in the SQL Server Enterprise Manager, you can see that the
AspNet_SqlCacheTablesForChangeNotificationtable has been removed for the database
SQL Server 2005 Cache Invalidation
As you’ve seen, standard SQL Server 2000 cache invalidation uses a table-level mechanism using a
polling model every few seconds to monitor what tables have changed SQL Server 2000’s technique
not only requires preparation of the database, its polling is rather expensive and its caching is quite
coarse
SQL Server 2005 supports a different, more granular series of notification that doesn’t require polling
Direct notification of changes is a built-in feature of SQL Server 2005 and is presented via the ADO.NET
SqlCommand For example:
Protected Sub Page_Load(ByVal sender as Object, ByVal e as System.EventArgs)
Response.Write("Page created: " + DateTime.Now.ToLongTimeString())
Dim connStr As String =
ConfigurationManager.ConnectionStrings("AppConnectionString1").ConnectionString
SqlDependency.Start(connStr)
Dim connection As New SqlConnection(connStr)
Trang 4Dim command as New SqlCommand("Select * FROM Customers", connection)
Dim depends as New SqlCacheDependency(command)
Connection.Open
GridView1.DataSource = command.ExecuteReader()
GridView1.DataBind()
Connection.Close
"Now, do what you want with the sqlDependency object like:
Response.AddCacheDependency(depends)
End Sub
SQL Server 2005 supports both programmatic and declarative techniques when caching Use the string
"CommandNotification"in theOutputCachedirective to enable notification-based caching for a page
as in this example You can specify SQL caching options either programmatically or declaratively, but
not both Note that you must first callSystem.Data.SqlClient.SqlDependency.Start, passing in the
connection string, to start the SQL notification engine
<%@ OutputCache Duration="3600" VaryByParam="none"
SqlDependency="CommandNotification"%>
Or, if you’re using a SqlDataSource control from within your ASP.NET page:
<asp:SqlDataSource EnableCaching="true" SqlCacheDependency="CommandNotification"
CacheDuration="2600" />
As data changes within SQL Server 2005, SQL and ADO.NET automatically invalidate data cached on
the Web server
Configuring Your ASP.NET Application
After you enable a database for SQL Server cache invalidation and also enable a couple of tables within
this database, the next step is to configure your application for SQL Server cache invalidation
To configure your application to work with SQL Server cache invalidation, the first step is to make some
changes to theweb.configfile In theweb.configfile, specify that you want to work with the Northwind
database, and you want ASP.NET connected to it
Listing 23-5 shows an example of how you should change yourweb.configfile to work with SQL Server
cache invalidation ThepollTimeattribute isn’t needed if you’re using SQL Server 2005 notification
because it uses database events instead of the polling needed for earlier versions
Listing 23-5: Configuring the web.config file
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<connectionStrings>
<add name="AppConnectionString1" connectionString="Data Source=localhost;
Trang 5User ID=sa;Password=wrox;Database=Northwind;Persist Security Info=False"
providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<caching>
<sqlCacheDependency enabled="true">
<databases>
<add name="Northwind" connectionStringName="AppConnectionString1"
pollTime="500" />
</databases>
</sqlCacheDependency>
</caching>
</system.web>
</configuration>
From this listing, you can see that the first thing established is the connection string to the Northwind
database using the<connectionStrings>element in theweb.configfile Note the name of the connec-tion string because it is utilized later in the configuraconnec-tion settings for SQL Server cache invalidaconnec-tion
The SQL Server cache invalidation is configured using the new<caching>element This element must
be nested within the<system.web>elements Because you are working with a SQL Server cache depen-dency, you must use a<sqlCacheDependency>child node You enable the entire process by using the
enabled = "true"attribute After this attribute is enabled, you work with the<databases>section You use the<add>element, nested within the<databases>nodes, to reference the Northwind database
The following table explains all the attributes of the<add>element
Name Thenameattribute provides an identifier to the SQL Server database
connectionStringName TheconnectionStringNameattribute specifies the name of the connection
Because the connection string in the preceding example is called
AppConnectionString1, you use this value for theconnectionStringName
attribute as well
to the next The default is 5 seconds or 500 milliseconds (as shown in the example) This is not needed for SQL Server 2005 notification
Now that theweb.configfile is set up correctly, you can start using SQL Server cache invalidation on
your pages ASP.NET makes a separate SQL Server request on a completely different thread to the
AspNet_SqlCacheTablesForChangeNotificationtable to see if thechangeIdnumber has been
incre-mented If the number is changed, ASP.NET knows that an underlying change has been made to the
SQL Server table and that a new result set should be retrieved When it checks to see if it should make
a SQL Server call, the request to the smallAspNet_SqlCacheTablesForChangeNotificationtable has a single result With SQL Server cache invalidation enabled, this is done so quickly that you really notice the difference
Trang 6Testing SQL Ser ver Cache Invalidation
Now that theweb.configfile is set up and ready to go, the next step is to actually apply these new
capa-bilities to a page Listing 23-6 is an example of a page using the SQL Server cache invalidation process
Listing 23-6: An ASP.NET page utilizing SQL Server cache invalidation
VB
<%@ Page Language="VB" %>
<%@ OutputCache Duration="3600" VaryByParam="none"
SqlDependency="Northwind:Customers"%>
<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Label1.Text = "Page created at " & DateTime.Now.ToShortTimeString () End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Sql Cache Invalidation</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Label ID="Label1" Runat="server"></asp:Label><br />
<br />
<asp:GridView ID="GridView1" Runat="server" DataSourceID="SqlDataSource1">
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" Runat="server"
SelectCommand="Select * From Customers"
ConnectionString="<%$ ConnectionStrings:AppConnectionString1 %>"
ProviderName="<%$ ConnectionStrings:AppConnectionString1.providername %>">
</asp:SqlDataSource>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<%@ OutputCache Duration="3600" VaryByParam="none"
SqlDependency="Northwind:Customers"%>
<script runat="server">
protected void Page_Load(object sender, System.EventArgs e)
{
Label1.Text = "Page created at " + DateTime.Now.ToShortTimeString();
}
</script>
The first and most important part of this page is theOuputCachepage directive that is specified at the top
of the file Typically, theOutputCachedirective specifies how long the page output is held in the cache
using theDurationattribute Next is theVaryByParamattribute The new addition is theSqlDependency
Trang 7attribute This enables a particular page to use SQL Server cache invalidation The following line shows the format of the value for theSqlDependencyattribute:
SqlDependency="database:table"
The value ofNorthwind:Customersspecifies that you want the SQL Server cache invalidation enabled for the Customers table within the Northwind database TheDurationattribute of theOutputCachedirective shows you that, typically, the output of this page is stored in the cache for a long time — but this cache
is invalidated immediately if the Customers table has any underlying changes made to the data that
it contains
A change to any of the cells in the Customers table of the Northwind database invalidates the cache,
and a new cache is generated from the result, which now contains a new SQL Server database request
Figure 23-6 shows an example of the page generated the first time it is run
Figure 23-6
From this figure, you can see the contents of the customer with theCustomerIDofALFKI For this entry,
go to SQL Server and change the value of theContactNamefromMaria AnderstoMary Anders If we
weren’t using SQL Server cache invalidation, this change would have done nothing to the output cache The original page output in the cache would still be present and the end user would still see theMaria
Andersentry for the duration specified in the page’sOutputCachedirective But because we’re using SQL Server cache invalidation, after the underlying information in the table is changed, the output cache is
invalidated, a new result set is retrieved, and the new result set is cached When a change has been made, you see the results as shown in Figure 23-7
Trang 8Figure 23-7
Notice also that the text ’’Page created at’’ includes an updated time indicating when this page was
rendered Need to stop working so late, eh?
Adding More Than One Table to a Page
The preceding example shows how to use SQL Server cache invalidation for a single table on the
ASP.NET page What do you do if your page is working with two or more tables?
To add more than one table, you use theOutputCachedirective shown here:
SqlDependency="database:table;database:table"
From this example, you can see that the value of theSqlDependencyattribute separates the databases
and tables with a semicolon If you want to work with both the Customers table and the Products table
of the Northwind database, you construct the value of theSqlDependencyattribute as follows:
SqlDependency="Northwind:Customers;Northwind:Products"
Attaching SQL Server Cache Dependencies
to the Request Object
In addition to changing settings in theOutputCachedirective to activate SQL Server cache invalidation,
you can also set the SQL Server cache invalidation programmatically To do so, use the
SqlCacheDepen-dencyclass, which is illustrated in Listing 23-7
Trang 9Listing 23-7: Working with SQL Server cache invalidation programmatically
VB
Dim myDependency As SqlCacheDependency = _
New SqlCacheDependency("Northwind", "Customers")
Response.AddCacheDependency(myDependency)
Response.Cache.SetValidUntilExpires(true)
Response.Cache.SetExpires(DateTime.Now.AddMinutes(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
C#
SqlCacheDependency myDependency = new SqlCacheDependency("Northwind", "Customers");
Response.AddCacheDependency(myDependency);
Response.Cache.SetValidUntilExpires(true);
Response.Cache.SetExpires(DateTime.Now.AddMinutes(60));
Response.Cache.SetCacheability(HttpCacheability.Public);
You first create an instance of theSqlCacheDependencyobject, assigning it the value of the database and the table at the same time TheSqlCacheDependencyclass takes the following parameters:
SqlCacheDependency(databaseEntryName As String, tablename As String)
You use this parameter construction if you are working with SQL Server 7.0 or with SQL Server 2000 If you are working with SQL Server 2005, you use the following construction:
SqlCacheDependency(sqlCmd As System.Data.SqlClient.SqlCommand)
After theSqlCacheDependencyclass is in place, you add the dependency to theCacheobject and set
some of the properties of theCacheobject as well You can do this either programmatically or through
theOutputCachedirective
Attaching SQL Server Cache Dependencies
to the Cache Object
In addition to attaching SQL Server cache dependencies to theRequestobject, you can attach them
to theCacheobject for data that can be cached much longer TheCacheobject is contained within the
System.Web.Cachingnamespace, and it enables you to work programmatically with the caching of
any type of objects Listing 23-8 shows a page that utilizes theCacheobject with theSqlDependency
object
Listing 23-8: Using the Cache object with the SqlDependency object
VB
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Data"%>
<%@ Import Namespace="System.Data.SqlClient"%>
Trang 10<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim myCustomers As DataSet myCustomers = CType(Cache("firmCustomers"), DataSet)
If myCustomers Is Nothing Then Dim conn As SqlConnection = _ New SqlConnection( _
ConfigurationManager.ConnectionStrings("AppConnectionString1").ConnectionString)
Dim da As SqlDataAdapter = _ New SqlDataAdapter("Select * From Customers", conn) myCustomers = New DataSet
da.Fill(myCustomers) Dim myDependency As SqlCacheDependency = _ New SqlCacheDependency("Northwind", "Customers") Cache.Insert("firmCustomers", myCustomers, myDependency) Label1.Text = "Produced from database."
Else
Label1.Text = "Produced from Cache object."
End If
GridView1.DataSource = myCustomers
GridView1.DataBind()
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Sql Cache Invalidation</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Label ID="Label1" Runat="server"></asp:Label><br />
<br />
<asp:GridView ID="GridView1" Runat="server"></asp:GridView>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">
protected void Page_Load(object sender, System.EventArgs e)
{
DataSet myCustomers;
myCustomers = (DataSet)Cache["firmCustomers"];
if (myCustomers == null)
{
SqlConnection conn = new