ASP.NET 缓存技术

ASP.NET 缓存技术
序言
有时候总听到同学说网站运行好慢,不知如何是好;有时候也总见到一些同学写的网站功能看起来非常好,但访问性能却极其的差。没有“勤俭节约”的意识,势必会造成“铺张浪费”。如何应对这种情况,充分利用系统缓存则是首要之道。
   系统缓存有什么好处呢?举个简单的例子,你想通过网页查询某些数据,而这些数据并非实时变化,或者变化的时间是有期限的。例如查询一些历史数据。那么每个用户每次查的数据都是一样的。如果不设置缓存,ASP.NET也会根据每个用户的请求重复查询n次,这就增加了不必要的开销。所以,可能的情况下尽量使用缓存,从内存中返回数据的速度始终比去数据库查的速度快,因而可以大大提供应用程序的性能。毕竟现在内存非常便宜,用空间换取时间效率应该是非常划算的。尤其是对耗时比较长的、需要建立网络链接的数据库查询操作等。
缓存功能是大型网站设计一个很重要的部分。由数据库驱动的Web应用程序,如果需要改善其性能,最好的方法是使用缓存功能。
缓存的分类
     从分布上来看,我们可以概括为客户端缓存和服务器端缓存。如图所示:
 
 


客户端缓存—— 这点大家都有直观的印象。比如你去一个新的网站,第一次可能要花一阵子时间才能载入整个页面。而以后再去呢,时间就会大大的缩短,原因就在于这个客户端缓存。现在的浏览器都比较智能,它会在客户机器的硬盘上保留许多静态的文件,比如各种gif,jpeg文件等等。等以后再去的时候,它会尽量使用本地缓存里面的文件。只有服务器端的文件更新了,或是缓存里面的文件过期了,它才会再次从服务器端下载这些东西。很多时候是IE替我们做了这件事情。
 
服务器端缓存—— 有些东西没法或是不宜在客户端缓存,那么我们只好在服务器端想想办法了。服务器端缓存从性质上看,又可以分为静态文件缓存和动态缓存两种。

(1)静态文件缓存
    好多页面是静态的,很少改动,那么这种文件最适于作静态缓存。静态缓存再此不做讲解。
(2)动态缓存
     动态缓存是比较有难度的。因为你在缓存的时候要时刻注意一个问题,那就是缓存的内容是不是已经过时了。因为内容过时了可能会有很严重的后果。比如网上买卖股票的网站。你给别人提供的价格是过时的,那人家非砍了你不可。缓存如何发现自己是不是过时就是一个非常复杂的问题。
 在ASP.NET中,常见的动态缓存主要有以下几种手段:
传统缓存方式
页面输出缓存。
页面局部缓存。
利用.NET提供的System.Web.Caching 缓存。
缓存依赖。
页面输出缓存
页面输出缓存是最为简单的缓存机制,该机制将整个ASP.NET页面内容保存在服务器内存中。当用户请求该页面时,系统从内存中输出相关数据,直到缓存数据过期。在这个过程中,缓存内容直接发送给用户,而不必再次经过页面处理生命周期。通常情况下,页面输出缓存对于那些包含不需要经常修改内容的,但需要大量处理才能编译完成的页面特别有用。需要读者注意的是,页面输出缓存是将页面全部内容都保存在内存中,并用于完成客户端请求。
在ASP.NET中页面缓存的使用方法非常的简单,只需要在aspx页的顶部加这样一句声明即可:
 
 

<%@ OutputCache Duration="60" VaryByParam="none" %> 
 
Duration 
缓存的时间(秒)。这是必选属性。如果未包含该属性,将出现分析器错误。
 
 
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="CacheWebApp._16_4_3.WebForm1" %>
<%@ OutputCache Duration="60" VaryByParam="none" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>页面缓存示例</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    </div>
    </form>
</body>
 
</html>
 
  
  
后台代码:
 
       protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                Label1.Text = DateTime.Now.ToString();
            }
 
        } 
  
 如果不加<%@ OutputCache Duration="60" VaryByParam="none" %>,每次刷新页面上的时间每次都是在变。而加了缓存声明以后,每次刷新页面的时间并不变化,60秒后才变化一次,说明数据被缓存了60秒。
 
VaryByParam
是指页面根据使用 POST 或 GET 发送的名称/值对(参数)来更新缓存的内容,多个参数用分号隔开。如果不希望根据任何参数来改变缓存内容,请将值设置为 none。如果希望通过所有的参数值改变都更新缓存,请将属性设置为星号 (*)。
例如:http://localhost:1288/Demo2.aspx?language=e
则可以在WebForm1.aspx页面头部声明缓存:<%@ OutputCache Duration="60" VaryByParam=" language " %>
以上代码设置页面缓存时间是60秒,并根据language参数的值来更新缓存,即language的值发生变化才更新缓存。
如果一直是Demo2.aspx?language=e访问该页,则页面会缓存当前数据,当language=c时又会执行后台代码更新缓存内容。
 
 
除此之外,@OutputCache 还有一些其他的属性。@OutputCache指令中的属性参数描述如下:
 
 
<%@ OutputCache Duration="#ofseconds"
   Location="Any | Client | Downstream | Server | None |
     ServerAndClient "
   Shared="True | False"
   VaryByControl="controlname"
   VaryByCustom="browser | customstring"
   VaryByHeader="headers"
   VaryByParam="parametername"
   CacheProfile="cache profile name | ''"
   NoStore="true | false"
   SqlDependency="database/table name pair | CommandNotification"
 
%>
 
 
  
 
CacheProfile
用于调用Web.config配置文件中设置的缓存时间。这是可选属性,默认值为空字符 ("")。
例如:在Web.config中加入配置:
 
<system.web>
    <caching>
        <outputCacheSettings>
            <outputCacheProfiles>
                <add name="CacheTest" duration="50" />
            </outputCacheProfiles>
        </outputCacheSettings>
 
 
</caching>
 
 
 
 
</system.web>
 
 
  
  
页面中声明:
 
 
 
 
<%@ OutputCache CacheProfile="CacheTest"  VaryByParam="none" %> 
 
 
 
注意:
包含在用户控件(.ascx 文件)中的 @ OutputCache 指令不支持此属性。在页中指定此属性时,属性值必须与 outputCacheSettings 节下面的 outputCacheProfiles 元素中的一个可用项的名称匹配。如果此名称与配置文件项不匹配,将引发异常。 
如果每个页面的缓存时间相同,则不需要每个页面设置,而是通过统一一个地方控制,这样就可以更好的统一控制所有页面的缓存时间。如果想改变缓存时间,只需要改一下web.config的配置信息即可,而不用每个页面去修改。
VaryByControl
通过控件文件中包含的服务器控件来改变缓存(值是控件ID,多控件用分号隔开)。
在 ASP.NET 页和用户控件上使用 @ OutputCache 指令时,需要该属性或 VaryByParam 属性。
 
 
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="CacheWebApp._16_4_3.WebForm2" %>
<%@ OutputCache Duration="60" VaryByParam="none" VaryByControl="DropDownList1" %>
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>根据控件页面缓存</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
         <%=DateTime.Now %>       
        <br>
    <asp:DropDownList ID="DropDownList1" runat="server">
        <asp:ListItem>beijing</asp:ListItem>
        <asp:ListItem>shanghai</asp:ListItem>
        <asp:ListItem>guangzhou</asp:ListItem>
        </asp:DropDownList>
        <asp:Button ID="Button1" runat="server" Text="提交" />
    </div>
    </form>
</body>
 
</html> 
 
以上代码设置缓存有效期是60秒,并且页面不随任何GET或POST参数改变(即使不使用VaryByParam属性,但是仍然需要在@ OutputControl指令中显式声明该属性)。如果用户控件中包含ID属性为“DropDownList1”的服务器控件(例如下拉框控件),那么缓存将根据该控件的变化来更新页面数据。
页面局部缓存
有时缓存整个页面是不现实的,因为页的某些部分可能在每次请求时都需要变化。在这些情况下,只能缓存页的一部分。顾名思义,页面部分缓存是将页面部分内容保存在内存中以便响应用户请求,而页面其他部分内容则为动态内容。页面部分缓存的实现包括两种方式:控件缓存和替换后缓存。
 
1. 控件缓存(也称为片段缓存)
    这种方式允许将需要缓存的信息包含在一个用户控件内,然后,将该用户控件标记为可缓存的,以此来缓存页面输出的部分内容。该选项允许缓存页面中的特定内容,而没有缓存整个页面,因此,每次都需重新创建整个页。例如,如果要创建一个显示大量动态内容(如股票信息)的页,其中有些部分为静态内容(如每周总结),这时可以将静态部分放在用户控件中,并允许缓存这些内容。
    在ASP.NET中,提供了UserControl这种用户控件的功能。一个页面可以通过多个UserControl来组成。只需要在某个或某几个UserControl里设置缓存。
    例如:
    那么可以在WebUserControl1.ascx的页头代码中添加声明语句:
 
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="CacheWebApp._16_4_5.WebUserControl1" %>
<%@ OutputCache Duration="60" VaryByParam="none" %>
 
<%=DateTime.Now %>  
 
  
 
     调用该控件的页面WebForm1.aspx代码:
 
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="CacheWebApp._16_4_5.WebForm1" %>
<%@ Register src="WebUserControl1.ascx" tagname="WebUserControl1" tagprefix="uc1" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>控件缓存</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    页面的:<%=DateTime.Now %>    
    </div>
    <div>
    控件的:<uc1:WebUserControl1 ID="WebUserControl11" runat="server" />
    </div>
    </form>
</body>
 
</html> 
 这时候刷新WebForm1.aspx页面时,页面的时间每次刷新都变化,而用户控件中的时间数据却是60秒才变化一次,说明对页面的“局部”控件实现了缓存,而整个页面不受影响。
 
2. 缓存后替换
   与控件缓存正好相反。它对整个页面进行缓存,但是页中的某些片段是动态的,因此不会缓存这些片段。ASP.NET页面中既包含静态内容,又包含基于数据库数据的动态内容。静态内容通常不会发生变化。因此,对静态内容实现数据缓存是非常必要的。然而,那些基于数据的动态内容,则不同。数据库中的数据可能每时每刻都发生变化,因此,如果对动态内容也实现缓存,可能造成数据不能及时更新的问题。对此问题如果使用前文所述的控件缓存方法,显然不切实际,而且实现起来很繁琐,易于发生错误。
   如何实现缓存页面的大部分内容,而不缓存页面中的局部某些片段。ASP.NET 2.0提供了缓存后替换功能。实现该项功能可通过以下三种方法:
    一是以声明方式使用Substitution控件,
    二是以编程方式使用Substitution控件API,
    三是以隐式方式使用控件。
    前两种方法的核心是Substitution控件,本节将重点介绍该控件,第三种方法仅专注于控件内置支持的缓存后替换功能,本节仅做简要说明。
 
(1) Substitution控件应用
     为提高应用程序性能,可能会缓存整个ASP.NET页面,同时,可能需要根据每个请求来更新页面上特定的部分。例如,可能要缓存页面的很大一部分,需要动态更新该页上与时间或者用户高度相关的信息。在这种情况下,推荐使用Substitution控件。Substitution控件能够指定页面输出缓存中需要以动态内容替换该控件的部分,即允许对整页面进行输出缓存,然后,使用Substitution控件指定页中免于缓存的部分。需要缓存的区域只执行一次,然后从缓存读取,直至该缓存项到期或被清除。动态区域,也就是Substitution控件指定的部分,在每次请求页面时都执行。Substitution控件提供了一种缓存部分页面的简化解决方案。
 
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="CacheWebApp._16_4_5.WebForm2" %>
<%@ OutputCache Duration="5" VaryByParam="none" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>缓存后替换示例</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    页面缓存的时间:<%= DateTime.Now.ToString() %>  
    </div>
    <div>   
       真实(替换)的时间:<asp:Substitution ID="Substitution1" runat="server" MethodName="getCurrentTime" />
    </div>
    </form>
</body>
 
</html>
  
 页面后台代码:
 
public partial class WebForm2 : System.Web.UI.Page
{
    public static string getCurrentTime(HttpContext context)
    {
        return DateTime.Now.ToString();
    }

  如上代码所示,Substitution控件有一个重要属性:MethodName。该属性用于获取或者设置当Substitution控件执行时为回调而调用的方法名称。该方法比较特殊,必须符合以下3条标准:
Ø  此方法必须被定义为静态方法;
Ø  此方法必须接受HttpContext类型的参数;
Ø  此方法必须返回String类型的值。
 
   在运行情况下,Substitution控件将自动调用MethodName属性所定义的方法。该方法返回的字符串即为要在页面中的Substitution控件的位置上显示的内容。如果页面设置了缓存全部输出,那么在第一次请求时,该页将运行并缓存其输出。对于后续的请求,将通过缓存来完成,该页上的其他代码不会再运行。但Substitution控件及其有关方法则在每次请求时都执行,并且自动更新该控件所表示的动态内容,这样就实现了整体缓存,局部变化的替换效果。
  如上代码所示,在代码头部通过@ OutputCache指令设置页面输出缓存过期时间为5秒,这意味着整个页面数据都应用了缓存功能。因此,“页面缓存的时间”所显示的时间值来自于数据缓存。这个时间值不会随着刷新页面而变化,仅当缓存过期时才会发生更新。Substitution控件的MethodName属性值为getCurrentTime。该控件显示的内容来自于getCurrentTime方法的返回值。尤为重要的是,虽然页面设置了输出缓存功能,但是每当页面刷新时,ASP.NET执行引擎仍然要重新执行Substitution控件,并将MethodName属性值指定的方法返回值显示在页面上,因此,显示的是当前最新时间。
随着页面的刷新,真实时间在变,而页面缓存的时间在指定的缓存时间内始终不变。 
  
Substitution控件API应用
上一小节介绍了以声明方式使用Substitution控件实现缓存后替换的应用。本节说明另一种实现方法。该方法的核心是以编程方式利用Substitution控件API实现缓存后替换,相对于以声明方式使用Substitution控件的方法具有更强灵活性。
通过为Substitution指定回调方法,实现和声明同样的效果。Substitution的回调方法必须是
HttpResponseSubstitutionCallback委托定义的方法,它有两个特征:
l  一是返回值必须是String,
l  二是参数有且仅有一个,并且是HttpContext类型。
当需要以编程方式,为缓存的输出响应动态生成指定的响应区域时,可以在页面代码中将某个方法(即回调方法)的名称作为参数(HttpResponseSubstitutionCallback)传递给Substitution。这样Substitution就能够使用回调方法,并将回调方法的返回值作为给定位置的替代内容显示出来。
需要注意的是,回调方法必须是线程安全的,可以是作为容器的页面或者用户控件中的静态方法,也可以是其他任意对象上的静态方法或实例方法。
下面演示一个以编程方式将 Substitution 控件添加到输出缓存网页。与(1)Substitution控件应用所示的示例完成同样功能。不同的是实现方式。
 
 
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm3.aspx.cs" Inherits="CacheWebApp._16_4_5.WebForm3" %>
<%@ OutputCache Duration="60" VaryByParam="none" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>缓存后替换-Substitution控件API应用</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        页面缓存的时间:<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    </div>
    <div>
        真实(缓存替换)的时间:
        <asp:PlaceHolder ID="PlaceHolder1" runat="Server"></asp:PlaceHolder>
    </div>
    </form>
</body>
 
</html>
  
 
 页面后台CS代码: 
 
protected void Page_Load(object sender, EventArgs e)
{
    //创建一个Substitution
    Substitution Substitution1 = new Substitution();
    //指定调用的回调方法名
    Substitution1.MethodName = "GetCurrentDateTime";           
    PlaceHolder1.Controls.Add(Substitution1);       
 
    Label1.Text=DateTime.Now.ToString();   
}
public static string GetCurrentDateTime(HttpContext context)
{
    return DateTime.Now.ToString();
}
  

    如上代码所示,页面使用@ OutputCache指令设置了输出缓存功能,其配置数据缓存过期时间为60秒。然而,页面其他内容都被缓存,通过Substitution调用的回调方法显示的内容是不被缓存的。

应用程序数据缓存
System.Web.Caching 命名空间提供用于缓存服务器上常用数据的类。此命名空间包括 Cache 类,该类是一个字典,您可以在其中存储任意数据对象,如哈希表和数据集。它还为这些对象提供了失效功能,并为您提供了添加和移除这些对象的方法。您还可以添加依赖于其他文件或缓存项的对象,并在从 Cache 对象中移除对象时执行回调以通知应用程序。
 
 
/// <summary>
/// 获取当前应用程序指定CacheKey的Cache对象值
/// </summary>
/// <param name="CacheKey">索引键值</param>
/// <returns>返回缓存对象</returns>
public static object GetCache(string CacheKey)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    return objCache[CacheKey];
}
/// <summary>
/// 设置当前应用程序指定CacheKey的Cache对象值
/// </summary>
/// <param name="CacheKey">索引键值</param>
/// <param name="objObject">缓存对象</param>
public static void SetCache(string CacheKey, object objObject)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    objCache.Insert(CacheKey, objObject);
}
/// <summary>
/// 设置当前应用程序指定CacheKey的Cache对象值
/// </summary>
/// <param name="CacheKey">索引键值</param>
/// <param name="objObject">缓存对象</param>
/// <param name="absoluteExpiration">绝对过期时间</param>
/// <param name="slidingExpiration">最后一次访问所插入对象时与该对象过期时之间的时间间隔</param>
public static void SetCache(string CacheKey, object objObject, DateTime absoluteExpiration, TimeSpan slidingExpiration)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    objCache.Insert(CacheKey, objObject, null, absoluteExpiration, slidingExpiration);
}       
protected void Page_Load(object sender, EventArgs e)
{
    string CacheKey = "cachetest";
    object objModel = GetCache(CacheKey);//从缓存中获取
    if (objModel == null)//缓存里没有
    {
        objModel = DateTime.Now;//把当前时间进行缓存
        if (objModel != null)
        {
            int CacheTime = 30;//缓存时间30秒
            SetCache(CacheKey, objModel, DateTime.Now.AddSeconds(CacheTime), TimeSpan.Zero);//写入缓存
        }
    }
    Label1.Text = objModel.ToString();

 
以上几种方法都很好的解决了数据缓存的问题,但由一个最大的问题是当数据发生变化了,而缓存里还是过期的数据,只有等缓存过期后才会重新获取最新的数据,这样的话,很多时候用户获取的数据都是和实际数据不一致的过期数据。这同样给用户造成了比较大的麻烦,怎么办呢?接着往下看。

  文件缓存依赖
这种策略让缓存依赖于一个指定的文件,通过改变文件的更新日期来清除缓存。
                                               
 
/// <summary>
/// 获取当前应用程序指定CacheKey的Cache对象值
/// </summary>
/// <param name="CacheKey">索引键值</param>
/// <returns>返回缓存对象</returns>
public static object GetCache(string CacheKey)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    return objCache[CacheKey];
}
/// <summary>
/// 设置以缓存依赖的方式缓存数据
/// </summary>
/// <param name="CacheKey">索引键值</param>
/// <param name="objObject">缓存对象</param>
/// <param name="cacheDepen">依赖对象</param>
public static void SetCache(string CacheKey, object objObject, System.Web.Caching.CacheDependency dep)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    objCache.Insert(
        CacheKey,
        objObject,
        dep,
        System.Web.Caching.Cache.NoAbsoluteExpiration, //从不过期
        System.Web.Caching.Cache.NoSlidingExpiration, //禁用可调过期
        System.Web.Caching.CacheItemPriority.Default,
        null);
}
protected void Page_Load(object sender, EventArgs e)
{
    string CacheKey = "cachetest";
    object objModel = GetCache(CacheKey);//从缓存中获取
    if (objModel == null) //缓存里没有
    {
        objModel = DateTime.Now;//把当前时间进行缓存
        if (objModel != null)
        {
            //依赖 C:\\test.txt 文件的变化来更新缓存
            System.Web.Caching.CacheDependency dep = new System.Web.Caching.CacheDependency("C:\\test.txt");
            SetCache(CacheKey, objModel, dep);//写入缓存
        }
    }
 
    Label1.Text = objModel.ToString();

 当我们改变test.txt的内容时,缓存会自动更新。这种方式非常适合读取配置文件的缓存处理。如果配置文件不变化,就一直读取缓存的信息,一旦配置发生变化,自动更新同步缓存的数据。
这种方式的缺点是,如果缓存的数据比较多,相关的依赖文件比较松散,对管理这些依赖文件有一定的麻烦。对于负载均衡环境下,还需要同时更新多台Web服务器下的缓存文件,如果多个Web应用中的缓存依赖于同一个共享的文件,可能会省掉这个麻烦。 

数据库缓存依赖
更多的时候,我们的服务器性能损耗还是在查询数据库的时候,所以对数据库的缓存还是显得特别重要,上面几种方式都可以实现部分数据缓存功能。但问题是我们的数据有时候是在变化的,这样用户可能在缓存期间查询的数据就是老的数据,从而导致数据的不一致。那有没有办法做到,数据如果不变化,用户就一直从缓存中取数据,一旦数据变化,系统能自动更新缓存中的数据,从而让用户得到更好的用户体验。
   答案是肯定的!.NET已经为我们提供了这样一种非常好的解决方法:SqlCacheDependency数据库缓存依赖。
  
实现步骤:
    下面就让我们看一下如何实现数据库缓存依赖功能:
第一步: 修改web.config,让项目启用SqlCacheDependency 。
将下列代码加入web.config的<system.web>节:   
 
<?xml version="1.0"?>
<configuration>
    <appSettings/>
    <connectionStrings>
        <add name="strcodematic" connectionString="data source=.;initial catalog=codematic;user id=sa;password=123456"  providerName="System.Data.SqlClient" />
    </connectionStrings>
    <system.web>
        <caching>
            <sqlCacheDependency enabled="true" pollTime="6000">
                <databases>
                    <add name="codematic" connectionStringName="strcodematic" />
                </databases>
            </sqlCacheDependency>         
        </caching>
    
        <compilation debug="true">
        </compilation>     
        <authentication mode="Windows"/>      
    </system.web>
</configuration>
  
 
这里的connectionStringName指定了在<connectionStrings>中添加的某一个连接字符串。name则是为该SqlCacheDependency起的名字,这个名字将在第3步中用到。
SqlCacheDependency类会自动完成对此配置节信息的读取以建立和数据库之间的联系。
 
 
注意:
在<databases>节的<add name="codematic" connectionStringName="strcodematic" />中的name属性值必须和第三步的Page_Load代码中System.Web.Caching.SqlCacheDependency("codematic", "P_Product"); 中的第一个参数(数据库名称)相一致。 
 

第二步:执行下述命令,为 数据库启用缓存依赖。
如果要配置SqlCacheDependency,则需要以命令行的方式执行。
aspnet_regsql.exe工具位于Windows\\Microsoft.NET\\Framework\\[版本]文件夹中。
aspnet_regsql -C "data source=.;initial catalog=BOOKDB;user id=sa;password=123456" -ed -et -t "BookInfo"
参数-C后面的字符串是连接字符串(请替换成自己所需要的值),
参数-t后面的字符串是数据表的名字。
 
 运行结果如图15-3所示:
 
 
图15-3  启用数据库缓存依赖
 命令执行后,在指定的数据库中会多出一个AspNet_SqlCacheTablesForChangeNotification表。


 
注意:
要使得7.0或者2000版本以上的SQLServer支持SqlCacheDependency特性,需要对数据库服务器执行相关的配置。
有两种方法配置SQLServer:
一 使用aspnet_regsql命令行工具,
二 使用SqlCacheDependencyAdmin类。
 
例如:
aspnet_regsql -S "server" -E -d "database" –ed  或者
aspnet_regsql -S "server" -E -d "database" -et -t "table"
如果是Sql验证的话要把-E换成,-U (用户名),-P (密码)
 
以下是该工具的命令参数说明:
-? 显示该工具的帮助功能;
-S 后接的参数为数据库服务器的名称或者IP地址;
-U 后接的参数为数据库的登陆用户名;
-P 后接的参数为数据库的登陆密码;
-E 使用当前登录用户的 Windows 集成认证进行身份验证。
-d 后接参数为对哪一个数据库采用SqlCacheDependency功能;
-C 连接数据库的连接字符串。如果您指定服务器(-S)和登录(-U和-P,或 -E)信息,则此选项不是必需的,因为连接字符串已经包含这些信息。
-t 后接参数为对哪一个表采用SqlCacheDependency功能;
-ed 允许对数据库使用SqlCacheDependency功能;
-dd 禁止对数据库采用SqlCacheDependency功能;
-et 允许对数据表采用SqlCacheDependency功能;
-dt 禁止对数据表采用SqlCacheDependency功能;
-lt 列出当前数据库中有哪些表已经采用sqlcachedependency功能。 
 

第三步:在代码中使用缓存,并为其设置SqlCacheDependency依赖:
   
 
/// <summary>
/// 获取当前应用程序指定CacheKey的Cache对象值
/// </summary>
/// <param name="CacheKey">索引键值</param>
/// <returns>返回缓存对象</returns>
public static object GetCache(string CacheKey)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    return objCache[CacheKey];
}
/// <summary>
/// 设置以缓存依赖的方式缓存数据
/// </summary>
/// <param name="CacheKey">索引键值</param>
/// <param name="objObject">缓存对象</param>
/// <param name="cacheDepen">依赖对象</param>
public static void SetCache(string CacheKey, object objObject, System.Web.Caching.CacheDependency dep)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    objCache.Insert(
        CacheKey,
        objObject,
        dep,
        System.Web.Caching.Cache.NoAbsoluteExpiration,//从不过期
        System.Web.Caching.Cache.NoSlidingExpiration,//禁用可调过期
        System.Web.Caching.CacheItemPriority.Default,
        null);
}
protected void Page_Load(object sender, EventArgs e)
{
    string CacheKey = "cachetest";
    object objModel = GetCache(CacheKey);//从缓存中获取
    if (objModel == null)//缓存里没有
    {
        objModel = GetData();//把当前时间进行缓存
        if (objModel != null)
        {
            //依赖数据库codematic中的P_Product表变化 来更新缓存
            System.Web.Caching.SqlCacheDependency dep = new System.Web.Caching.SqlCacheDependency("codematic", "P_Product");
            SetCache(CacheKey, objModel, dep);//写入缓存
        }
    }
               
    GridView1.DataSource = (DataSet)objModel;
    GridView1.DataBind();
}
 
//查询数据
private DataSet GetData()
{
    string conString = "data source=127.0.0.1;initial catalog=codematic;user id=sa;password=";
    string strSQL = "SELECT * FROM P_Product";
    SqlConnection myConnection = new SqlConnection(conString);
    DataSet ds = new DataSet();
    myConnection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter(strSQL, myConnection);
    adapter.Fill(ds, "Product");
    myConnection.Close();
    return ds;
}
  
 
    从以上代码可以看出,和文件依赖基本相同,只是在存放缓存SetCache时存入的依赖对象不同罢了。这里用的是SqlCacheDependency。
     其中,创建SqlCacheDependency的构造方法:
 
public SqlCacheDependency (string databaseEntryName,string tableName) 
 
l  databaseEntryName :是在Web.config 文件的 caching 节的 sqlCacheDependency 的 databases 元素中定义的数据库的名称。
l  tableName :与 SqlCacheDependency 关联的数据库表的名称。
    这样,只有当P_Product表的内容发生变化时,查询操作才会重新查询数据更新缓存的内容,可以大大减少数据库的重复查询和提高系统的性能和运行效率。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值