ASP.NET的缓存依赖机制SQL缓存依赖篇

高效使用使用SQL缓存依赖
 
ASP.NET Framework新增的一个非常强大的功能是SQL缓存依赖。该功能允许底层数据库中的数据修改时,自动地重新载入缓存的数据。

在使用绝对缓存过期策略或者弹性缓存过期策略时有一个权衡,对于性能和陈旧数据的权衡。例如,如果在内存中缓存数据20秒,则这20秒内显示的数据可能是过期的。

对于大多数应用程序来说,就算显示过期数据也没什么关系。例如,如果我们构建一个论坛讨论区,则每个用户都能接受新的主题可能不是实时显示的。

然而,某些类型的应用程序则绝对不能有陈旧数据。例如,如果我们创建一个股票交易网站或者拍卖网站,那么每一秒的数据都很关键。

ASP.NET Framework支持的SQL缓存依赖使得使用缓存时可以充分利用缓存,并且最小化陈旧数据。当使用SQL缓存依赖时,可以自动监测底层数据库中的数据是否变更,并刷新缓存中的数据。

ASP.NET Framework支持两种类型的SQL缓存依赖:轮询和推。可以对任何最近版本的Microsoft SQL Server,包括Microsoft SQL Server 2005 Express、Microsoft SQL Server 2000和Microsoft SQL Server 7.0,使用轮询SQL缓存依赖。第二种类型的缓存依赖——推SQL缓存依赖则只能用于Microsoft SQL Server 2005和Microsoft SQL Server 2005 Express,因为它依赖SQL Server 2005 Service Broker。

可以对页面输出缓存、数据源控件缓存和数据缓存使用任意类型的SQL缓存依赖。接下来将依次讨论每一种场景。

4.6.1 使用轮询SQL缓存依赖

轮询SQL缓存依赖是最灵活的SQL缓存依赖类型,所以对大多数应用程序来说,推荐使用轮询SQL缓存依赖。可以使用轮询SQL缓存依赖来检测数据库表的修改。

实质上,轮询SQL缓存依赖使用数据库触发器。当表被修改时,触发器被触发,名为AspNet_ SqlCacheTablesForChangeNotification的数据库表的一行数据将被更新,用来记录表被修改的情况。

ASP.NET Framework使用一个后台线程,用来定期轮询数据库表的修改信息。如果有修改,则依赖于数据库表的缓存项目从缓存中移除。

如果使用轮询SQL缓存依赖,则可以消除大多数和数据库的通信消费。如果数据库表还没有更改, Web服务器和数据库服务器之间唯一的通信是检查AspNet_SqlCacheTablesForChange- Notification表的修改的查询。

因为轮询SQL缓存依赖必须轮询数据库的修改,使用轮询SQL缓存依赖的缓存项目只有在数据修改时才会立即失效。轮询时间间隔的大小决定了缓存数据的陈旧程度,这个时间间隔可为任意需要的值。

4.6.2 配置轮询SQL缓存依赖

在使用轮询SQL缓存依赖之前,必须执行下面两步配置。

(1) 必须对一个或多个数据库表启用SQL缓存依赖。

(2) 必须在Web配置文件中配置SQL缓存依赖。

让我们分别讨论每一步。

1. 为轮询SQL缓存依赖配置数据库

可以使用框架中的SqlCacheDependencyAdmin类来配置SQL Server数据库以支持轮询SQL缓存依赖。该类包含如下方法。

l    DisableNotifications——用于禁用数据库轮询SQL缓存依赖。移除所有用于表和存储过程的轮询缓存依赖。

l    DisableTableForNotification——用于禁用特定的数据库表的轮询SQL缓存依赖。

l    EnableNotifications——通过添加所有必需的数据库对象,启用数据库的轮询SQL缓存依赖。

l    EnableTableForNotifications——启用特定数据库表的轮询SQL缓存依赖。

l    GetTablesEnabledForNotifications——用于返回所有启用了轮询SQL缓存依赖的表。

不应该在ASP.NET页面中使用SqlCacheDependencyAdmin类,因为调用该类的方法需要创建表、存储过程和trigger。出于安全考虑,ASP.NET进程不应该被赋予这些权限,而是应该在一个命令行工具中使用SqlCacheDependencyAdmin类。

ASP.NET Framework包括一个名为aspnet_regsql的命令行工具,可用它来配置数据库以支持轮询SQL缓存依赖。该工具可以用于Microsoft SQL Server 7.0、Microsoft SQL Server 2000和Microsoft SQL Server 2005。遗憾的是,aspnet_regsql的命令行工具不支持本地Microsoft SQL Server 2005实例(不过我们马上会修复该限制)。

aspnet_regsql工具存放在下面文件夹中:

c:\Windows\Microsoft.NET\Framework\v2.0.50727

注解   如果打开Microsoft .NET Framework SDK程序组的SDK命令行提示程序,则不需要浏览Microsoft. NET目录就能执行aspnet_regsql命令行工具。

执行下面的命令可启用Pubs数据库的SQL缓存依赖:

aspnet_regsql -C "Data Source=localhost;Integrated Security=True;Initial

Catalog=Pubs" -ed

该命令将创建AspNet_SqlCacheTablesForChangeNotification数据库表,并添加一组存储过程到连接字串指定的数据库。

启用一个数据库之后,就可以用如下命令来启用特定表的SQL缓存依赖:

aspnet_regsql -C "Data Source=localhost;Integrated Security=True;Initial

Catalog=Pubs" -et -t Titles

该命令启用了Titles数据库表的SQL缓存依赖。它会给Titles数据库表创建一个新的trigger,并添加一行新记录到AspNet_SqlCacheTablesForChangeNotification表。

遗憾的是,不能使用标准的aspnet_regsql工具来启用本地SQL Server 2005 Express数据库实例的轮询SQL缓存依赖。此工具不允许在连接字符串中使用AttachDBFileName参数。

为了解除该限制,我编写了一个名为enableNotifications的自定义命令行工具,可以用它来处理本地SQL Express数据库。该工具包含在随书附带资源中。

要使用enableNotifications工具,先打开命令行工具,然后浏览包含本地SQL Express数据库的文件夹。接着,执行需要启用轮询SQL缓存依赖的数据库文件的名称和数据表的名称的命令。例如,下面的命令启用了MyDatabase.mdf数据库中的Movies数据库:

enableNotifications "MyDatabase.mdf" "Movies"

enableNotifications工具只能处理Microsoft SQL Server Express 2005数据库的实例。不能使用该工具处理其他版本的Microsoft SQL Server。

注意   当使用enableNotifications工具时,必须先浏览希望启用轮询SQL缓存依赖的数据所在的文件夹。

2. 为轮询SQL缓存依赖配置应用程序

设置数据库支持轮询SQL缓存依赖,必须要配置应用程序才能轮询数据库。可以使用Web配置文件中的caching元素的sqlCacheDependency子元素来配置轮询SQL缓存依赖。

例如,代码清单4-41所示的文件使得应用程序每5秒钟(5 000毫秒)对AspNet_SqlCacheTables- ForChangeNotification表进行一次轮询,观察是否有更改。

代码清单4-41 Web.Config

<configuration>

<connectionStrings>

    <add name=”Movies” connectionString=”Data Source=.\SQLEXPRESS;

      AttachDbFilename=|DataDirectory|MyDatabase.mdf;Integrated Security=True;

User Instance=True” />

</connectionStrings>

<system.web>

    <caching>

     <sqlCacheDependency enabled=”true” pollTime=”5000”>

         <databases>

           <add

            name=”MyDatabase”

            connectionStringName=”Movies” />

       </databases>

      </sqlCacheDependency>

    </caching>

</system.web>

</configuration>

4.6.3 对页面输出缓存使用轮询SQL缓存依赖

配置好轮询SQL缓存依赖后,就能对页面输出缓存使用SQL依赖了。例如,代码清单4-42所示的页面被输出缓存了,直到Movies数据库表被修改,缓存才失效。

代码清单4-42 PollingSQLOutputCache.aspx

<%@ Page Language="C#" %>

<%@ OutputCache Duration="9999" VaryByParam="none"

   SqlDependency="MyDatabase:Movies" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Polling SQL Output Cache</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

  

    <%= DateTime.Now.ToString("T") %>

    <hr />

  

    <asp:GridView

        id="grdMovies"

       DataSourceID="srcMovies"

        Runat="server" />

  

    <asp:SqlDataSource

        id="srcMovies"

        ConnectionString="<%$ ConnectionStrings:Movies %>"

        SelectCommand="SELECT Title, Director FROM Movies"

        Runat="server" />

 

    </div>

    </form>

</body>

</html>

代码清单4-42所示的页面包含了一个带有sqlDependency特性的<%@ OutputCache %>指令。SqlDependency特性的值为Web配置文件中启用了SQL依赖的数据库和数据库表的名称。

如果在浏览器中打开如代码清单4-42所示的页面,并且多次单击浏览器的重新载入按钮,你会注意到显示的时间不会变,因为该页被输出缓存了(见图4-16)。

图4-16 对页面输出缓存使用轮询SQL缓存依赖

然而,当修改Movies数据库表时,页面缓存将会自动失效(5秒钟内)。再次单击重新载入按钮时,会显示修改的数据。

如果希望让一个页面依赖多个数据库表,则需要将sqlDependecy特性设置为一组用分号分隔的数据库和数据库表名的列表。

注解   也可以在一个用户控件中使用<%@ OutputCache %> 指令来使用轮询SQL缓存依赖。也就是说,可以使用轮询SQL缓存依赖来实现部分页面缓存。

4.6.4 对数据源缓存使用轮询SQL缓存依赖

要对SqlDataSource和ObjectDataSource控件使用轮询SQL缓存依赖,只需要设置sqlCache- Dependency属性。例如,代码清单4-43所示的页面缓存了SqlDataSource控件的输出,直到Movies数据库表被修改,它才失效。

代码清单4-43 PollingSQLDataSourceCache.aspx

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    protected void srcMovies_Selecting(object sender, SqlDataSourceSelectingEventArgs e)

    {

        lblMessage.Text = "Retrieving data from database";

    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Polling SQL DataSource Cache</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

  

    <asp:Label

        id="lblMessage"

        EnableViewState="false"

        Runat="server" />

    <hr />

  

    <asp:GridView

        id="grdMovies"

        DataSourceID="srcMovies"

        Runat="server" />

  

    <asp:SqlDataSource

        id="srcMovies"

        ConnectionString="<%$ ConnectionStrings:Movies %>"

        SelectCommand="SELECT Title, Director FROM Movies"

        EnableCaching="true"

        SqlCacheDependency="MyDatabase:Movies"

        OnSelecting="srcMovies_Selecting"

        Runat="server" />

  

    </div>

    </form>

</body>

</html>

在代码清单4-43中,SqlDataSource控件包括了EnableCaching属性和SqlCacheDependency属性。数据库名和数据库表名都分配了SqlCacheDependency属性(数据库名必须与配置在Web配置文件<sqlCacheDependency>元素中的数据库名相对应)。

如果需要监视多个数据库表,则要给SqlCacheDependency属性指派一组用分号分隔的数据库和数据库表的名称列表。

4.6.5 对数据缓存使用轮询SQL缓存依赖

我们也可以对Cache对象使用轮询SQL缓存依赖,用SqlCacheDependency对象来代表一个轮询SQL缓存依赖。

例如,代码清单4-44所示的页面创建了一个SqlCacheDependency对象,它代表Movies数据库表。当DataTable添加到Cache对象时,DataTable就关联到SqlCacheDependency对象。

代码清单4-44 PollingSQLDataCache.aspx

<%@ Page Language="C#" Trace="true" %>

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.SqlClient" %>

<%@ Import Namespace="System.Web.Configuration" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    void Page_Load()

    {

        DataTable movies = (DataTable)Cache["Movies"];

        if (movies == null)

        {

            movies = GetMoviesFromDB();

            SqlCacheDependency sqlDepend = new SqlCacheDependency("MyDatabase", "Movies");

            Cache.Insert("Movies", movies, sqlDepend);

        }

        grdMovies.DataSource = movies;

        grdMovies.DataBind();

    }

    private DataTable GetMoviesFromDB()

    {

        Trace.Warn("Retrieving data from database");

        string conString = WebConfigurationManager.ConnectionStrings["Movies"].ConnectionString;

        SqlDataAdapter dad = new SqlDataAdapter("SELECT Title,Director FROM Movies", conString);

        DataTable movies = new DataTable();

        dad.Fill(movies);

        return movies;

    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Polling SQL Data Cache</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

  

    <asp:GridView

        id="grdMovies"

        Runat="server" />

  

    </div>

    </form>

</body>

</html>

代码清单4-44中创建了SqlCacheDependency类的一个实例。一个数据库名和表名传递给SqlCacheDependency类的构造函数。当DataTable添加到Cache时,该类就用作Cache.Insert()的一个参数。

注解   如果需要创建多个数据库表的依赖,则需要创建多个SqlCacheDependency对象并用Aggregate- CacheDependency类的实例表示多个依赖。

4.6.6 使用推SQL缓存依赖

在使用Microsoft SQL Server 2005时,除了轮询SQL缓存依赖,还可以使用推SQL缓存依赖。Microsoft SQL Server 2005包含一个名为查询通知的功能,它在后台使用Microsoft SQL Server 2005的Service Broker。这个Service Broker可以在数据库中的数据变更时自动给应用程序发送一个消息。

注意   可以用SQL Server Express创建两种类型的数据库:本地和服务器数据库。不应对本地数据库使用推依赖,而是只能对服务器数据库使用推依赖。
不能使用Visual Web Developer创建一个服务器数据库。只能使用完全功能的Visual Studio 2008或者从Microsoft MSDN网站(msdn.microsoft.com)下载Microsoft SQL Server Management Studio Express来创建服务器数据库。

相比于轮询SQL缓存依赖,使用推依赖的好处是ASP.NET应用程序不必定时地轮询数据库的修改。如果有修改,数据库会通知应用程序。

也有不太好的一面,使用推依赖的查询类型有诸多限制。下面是比较显著的一些限制。

l    查询必须使用两部分的表名(例如,dbo.Movies而不是Movies)。

l    查询必须包含一个显式的列名列表(不能使用*)。

l    查询不能引用视图、继承表、临时表或表变量。

l    查询不能引用大对象类型,如Text、NText和Image列。

l    查询不能包含子查询、外联结或子联结。

l    查询不能使用DISTINCT、COMPUTE、COMPUTE BY或者INSERT关键字。

l    查询不能使用许多聚合函数,包括AVG、COUNT(*)、MAX和MIN。

这里只是一个不完整的查询限制的列表。要查看完整的列表,可以参考SQL Server 2005在线图书或MSDN网站(msdn.microsoft.com)的“创建一个通知查询”的主题。

例如,下面这个简单的查询不能工作:

SELECT * FROM Movies

该查询不能工作有两个原因。第一是不能使用星号(*)来代表列,第二是必须使用两部分的表名。而下面这个查询就能工作:

SELECT Title,Director FROM dbo.Movies

可以对推SQL缓存依赖使用存储过程。不过,每一个存储过程中的SELECT语句必须满足刚才列出的限制列表。

4.6.7 配置推SQL缓存依赖

要启用推SQL缓存依赖,必须完成下面两步配置。

l    必须配置数据库启用SQL Server 2005 Service Broker。

l    必须配置应用程序开始监听通知。

在这一小节,你将了解到如何完成这两个配置步骤。

注意   遗憾的是,当推缓存依赖失败时,不会有任何错误报告发送到事件日志。这就使得调试变得极其困难。我建议,完成这一小节讨论的配置修改后,重新启动Web服务器和数据库服务器。

1. 为推SQL缓存依赖配置数据库

在使用推SQL缓存依赖之前,必须启用Microsoft SQL Server 2005 Service Broker。可以执行下面的SQL查询来检查Service Broker是否已经为特定的数据库激活:

SELECT name, is_broker_enabled FROM sys.databases

如果Service Broker还没有启用,则要执行ALTER DATABASE命令来启用它。例如,下面的SQL命令为MyMovies数据库启用了Service Broker:

ALTER DATABASE MyMovies SET ENABLE_BROKER

最后,ASP.NET进程必须有足够的权限来订阅查询通知。当一个ASP.NET页面由IIS处理时,页面在NT Authority WET WORK SERVICE账号(对于Windows Server 2003或Vista)或者ASPNET账号(对于其他操作系统,如Windows XP)上下文中执行。

执行下面的SQL命令能给YOURSERVER服务器上的本地ASPNET账号赋予需要的权限:

GRANT SUBSCRIBE QUERY NOTIFICATIONS TO "YOURSERVER\ASPNET"

当使用Visual Web Developer的Web服务器来请求一个ASP.NET页面时,ASP.NET页面在当前用户账号的安全上下文中执行。因此,当使用文件系统网站时,需要对当前账号执行SUBSCRIBE QUERY NOTIFICATIONS来授权。

注解    推SQL缓存依赖并不使用SQL Server 2005的通知服务。

2. 为推SQL缓存依赖配置应用程序

在应用程序可以接收到变更通知之前,必须启用查询通知监听器。可以在如代码清单4-45所示的Global.asax文件中启用监听器。

代码清单4-45 Global.asax

<%@ Application Language=”C#” %>

<%@ Import Namespace=”System.Data.SqlClient” %>

<%@ Import Namespace=”System.Web.Configuration” %>

<script runat=”server”>

    void Application_Start(object sender, EventArgs e)

    {

        // Enable Push SQL cache dependencies

        string conString = WebConfigurationManager.ConnectionStrings

        ➥["MyMovies"].ConnectionString;

        SqlDependency.Start(conString);

    }

</script>

Application_Start事件处理程序只在应用程序刚开始运行时执行一次。在代码清单4-45中,SqlDependency.Start()方法使用一个指向SQL Express的MyMovies服务器数据库的连接字符串调用。

注意   代码清单4-45中的代码在随书附带资源中的Global.asa文件中被注释了,这样它就不会影响本章前面讨论的所有代码。接下来,去掉注释并使用示例代码。

4.6.8 对页面输出缓存使用推SQL缓存依赖

当缓存整个ASP.NET页面时,可以使用推SQL缓存依赖。如果包含在页面上的任何SQL命令的结果有改变,页面就会自动从缓存中删除。

SqlCommand对象包含一个NotificationAutoEnlist属性,该属性默认值为true。当Notification- AutoEnlist启用时,页面和命令之间会自动创建一个推缓存依赖。

例如,代码清单4-46所示的页面包含<%@ OUtputCache %>指令,其中SqlDependency特性的值为CommandNotification。

代码清单4-46 PushSQLOutputCache.aspx

<%@ Page Language="C#" %>

<%@ OutputCache Duration="9999" VaryByParam="none"

   SqlDependency="CommandNotification" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

   <title>Push SQL Output Cache</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

  

    <%= DateTime.Now.ToString("T") %>

    <hr />

       

    <asp:GridView

        id="grdMovies"

        DataSourceID="srcMovies"

        Runat="server" />

  

    <asp:SqlDataSource

        id="srcMovies"

        ConnectionString="<%$ ConnectionStrings:MyMovies %>"

        SelectCommand="SELECT Title, Director FROM dbo.Movies"

        Runat="server" />

  

    </div>

    </form>

</body>

</html>

代码清单4-46所示的页面包含一个SqlDataSource控件,可以从Movies数据库表获取所有记录。注意,SqlDataSource控件使用了显式列名的SQL查询,并使用了两部分格式表名。这些都是使用推缓存依赖必需的。

代码清单4-46所示的页面显示了当前时间。如果从浏览器请求该页面并刷新页面,时间不会变化。只有修改Movies数据表时,时间才会变。

注意   代码清单4-46所示的页面连接到一个名为MyMovies的服务器数据库。不要对本地SQL Express数据库使用推依赖。该页面使用一个Movies数据库表,创建这个表的SQL命令如下:

CREATE TABLE Movies

(

Id int IDENTITY NOT NULL,

Title nvarchar(100) NOT NULL,

Director nvarchar(50) NOT NULL,

EntryDate datetime NOT NULL DEFAULT GetDate()

)

注意   不能对包含<%@ OutputCache %>指令的用户控件使用推SQL缓存依赖。也就是说,不能对部分页面缓存使用推SQL缓存依赖。

4.6.9 对数据源缓存使用推SQL缓存依赖

也可以对SqlDataSource和ObjectDataSource使用推SQL缓存依赖,只需设置SqlCacheDependency属性即可。不同于轮询依赖,使用推依赖需要设置SqlCacheDependency属性为CommandNotification。

例如,代码清单4-47所示的页面包含了一个SqlDataSource控件,设置了EnableCaching和SqlDependency属性集。

代码清单4-47 PushSQLDataSourceCache.aspx

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    protected void srcMovies_Selecting(object sender, SqlDataSourceSelectingEventArgs e)

    {

        lblMessage.Text = "Retrieving data from database";

    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Push SQL DataSource Cache</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

  

    <asp:Label

        id="lblMessage"

        EnableViewState="false"

        Runat="server" />

    <hr />

  

    <asp:GridView

        id="grdMovies"

        DataSourceID="srcMovies"

        Runat="server" />

  

    <asp:SqlDataSource

        id="srcMovies"

        ConnectionString="<%$ ConnectionStrings:MyMovies %>"

        SelectCommand="SELECT Title, Director FROM dbo.Movies"

        EnableCaching="true"

        SqlCacheDependency="CommandNotification"

        OnSelecting="srcMovies_Selecting"

        Runat="server" />

  

    </div>

    </form>

</body>

</html>

在代码清单4-47中,SqlDataSource控件包括一个Selecting事件处理程序。因为该事件在数据不能从缓存中获得时触发,所以可以用它来判断数据从缓存中返回还是从数据库服务器中返回(见图4-17)。

图4-17 对DataSource控件使用推SQL缓存依赖

注意   代码清单4-47所示的页面连接到一个名为MyMovies的服务器数据库。不要对本地SQL Express数据库使用推依赖。该页面使用一个Movies数据库表,创建这个表的SQL命令如下:

CREATE TABLE Movies

(

Id int IDENTITY NOT NULL,

Title nvarchar(100) NOT NULL,

Director nvarchar(50) NOT NULL,

EntryDate datetime NOT NULL DEFAULT GetDate()

)

4.6.10 对数据缓存使用推SQL缓存依赖

也可以对Cache对象使用推SQL缓存依赖。可以用一个SqlCacheDependency类的实例代表一个推SQL缓存依赖。

例如,在代码清单4-48所示的Page_Load()事件处理程序中,一个DataTable添加到缓存,它代表了Movies数据库表的内容。这个DataTable显示在一个GridView控件中。

代码清单4-48 PushSQLDataCache.aspx

<%@ Page Language="C#" Trace="true" %>

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.SqlClient" %>

<%@ Import Namespace="System.Web.Configuration" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    void Page_Load()

    {

        DataTable movies = (DataTable)Cache["Movies"];

        if (movies == null)

        {

            Trace.Warn("Retrieving data from database");

           string conString = WebConfigurationManager.ConnectionStrings["MyMovies"].ConnectionString;

              SqlDataAdapter dad = new SqlDataAdapter("SELECT Title,Director FROM dbo.Movies", conString);

            SqlCacheDependency sqlDepend = new SqlCacheDependency(dad.SelectCommand);

            movies = new DataTable();

            dad.Fill(movies);

            Cache.Insert("Movies", movies, sqlDepend);

        }

        grdMovies.DataSource = movies;

        grdMovies.DataBind();

    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

    <title>Push SQL Data Cache</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

  

    <asp:GridView

        id="grdMovies"

        Runat="server" />

  

    </div>

    </form>

</body>

</html>

注意,SqlCacheDependency类的实例被创建了。一个SqlCommand对象被传递给了SqlCacheDependency类的构造函数。如果SqlCommand的结果变化了,则这个DataTable会自动从缓存中删除。

这些命令的顺序很重要。必须在执行该命令之前创建SqlCacheDependency对象。如果在创建SqlCacheDependency对象之前调用Fill()方法,则依赖会被忽略。

注意   代码清单4-48所示的页面连接到一个名为MyMovies的服务器数据库。不要对本地SQL Express数据库使用推依赖。该页面使用一个Movies数据库表,创建这个表的SQL命令如下:

CREATE TABLE Movies

(

Id int IDENTITY NOT NULL,

Title nvarchar(100) NOT NULL,

Director nvarchar(50) NOT NULL,

EntryDate datetime NOT NULL DEFAULT GetDate()

)
本文来自租赁宝网技术支持,参考网站:http://www.zulinbao.com

原文地址:https://www.cnblogs.com/systemxgl/p/1942875.html