ASP.NET缓存技术

1 ASP.NET缓存
(1) 缓存技术概述
在网站应用中,网站的应用程序可以将频繁访问的数据以及需要大量处理时间来创建的数据存储在内存中,从而提高网站的整体性能。例如,如果应用程序使用复杂的逻辑来处理大量数据,然后再将数据作为用户频繁访问的报表返回,避免在用户每次请求数据时重新创建报表可以提高效率。同样,如果应用程序包含一个处理复杂数据但不需要经常更新的页,则在每次请求时服务器都重新创建该页会使工作效率低下。
说明:为了提高应用程序的性能,ASP.NET使用两种基本的缓存机制来提供缓存功能。第一种机制是应用程序缓存,它允许缓存所生成的数据,如DataSet或自定义报表业务对象。第二种机制是页输出缓存,它保存页处理输出,并在用户再次请求该页时,重用所保存的输出,而不是再次处理该页。
页输出缓存:页输出缓存在内存中存储处理后的ASP.NET页的内容。这一机制允许ASP.NET向客户端发送页响应,而不必再次经过页处理生命周期。页输出缓存对于那些不经常更改,但需要大量处理才能创建的页特别有用。
应用程序缓存:应用程序缓存提供了一种编程方式,可通过键/值对将任意数据存储在内存中。使用应用程序缓存的优点是由ASP.NET管理缓存,它会在项过期、无效或内存不足时移除缓存中的项。还可以配置应用程序缓存,以便在移除项时通知应用程序。
(2) 缓存新增功能
缓存配置文件:缓存配置文件能够在应用程序的web.config文件中创建缓存设置,然后在单个页上引用这些设置。可以将缓存设置同时应用于多页。例如,可以定义一个缓存配置文件,它将页的缓存持续时间设置为一天,然后可以配置各个页使用这个缓存配置文件,并且这些页的缓存持续时间为一天。如果将某个缓存配置文件更改为不使用缓存,将停止缓存这些页。
自定义缓存依赖项:在ASP.NET 2.0中,可以根据应用程序特定情况创建自己的自定义缓存依赖项。若要创建自定义缓存依赖项,需要从CacheDependency继承的类并在自定义类中实现自己的依赖项方法。例如,可以创建在Web服务中轮询数据的依赖项。数据发生变化时,使缓存数据无效。
SqlCacheDependency:ASP.NET 2.0引入了SqlCacheDependency类,它能够在缓存中配置一个项,以便在SQL Server数据库中的表或行上拥有依赖项。当表中或特定行中发生更改时,具有依赖项的缓存项便会失效并从缓存中移除。ASP.NET 2.0能够在SQL Server 7.0、SQL Server 2000和SQL Server 2005中设置表的依赖项。使用SQL Server 2005时,还可以设置特定记录的依赖项。
缓存后替换:ASP.NET 2.0现在支持缓存后替换,它能够将页中的某一部分配置不可缓存。因此,尽管缓存了该页,但在再次请求该页时,将重新处理它的部分内容。
(3) 缓存配置
缓存的配置可以通过多种方式来实现,这几种方式分别为配置文件配置、单个页面配置和用户控件的配置。
注意:配置文件配置主要是指可以在应用程序配置层次结构的任何配置文件中配置页面输出缓存设置,包括machine.config文件或特定于应用程序的web.config文件。
单个页面配置是指可以在单个页面中以声明方式或编程方式设置缓存选项,还可将在配置文件中创建的缓存配置文件应用于单个页面。用户控件配置是指可以在单个用户控件中以声明方式或编程方式设置缓存,对于在其他情况下不缓存的页面内容来说,这是一种简便的缓存方法。
配置文件配置:由于machine.config文件的配置方法与web.config文件配置类似,所以这里只介绍如何配置web.config文件使用缓存。在web.config文件中,有两个顶级配置节用于页输出缓存:OutputCacheSection和OutputCacheSettingsSection。OutputCacheSection节用于配置应用程序范围的设置,例如是否启用还是禁用页输出缓存。可以向OutputCacheSection添加enableOutputCache="false"来对整个应用程序禁用页输出缓存。由于配置文件中的设置要优先于单个页面中的缓存设置,因此,示例设置将导致不使用输出缓存。OUtputCacheSettingsSection用于配置可由单个页面使用的配置文件和依赖项。例如,下面的代码创建了一个名为CacheProfile1的OutputCacheProfiles,它将实现缓存页60秒:
<outputCacheSettings>
 <outputCacheProfiles>
  <add name="CacheProfile1" duration="60" />
 </outputCacheProfiles>
</outputCacheSettings>
页面缓存配置设置:通过应用在配置文件中定义的缓存配置文件,可以配置单个页中的缓存。也可以在@OutputCache指令中配置单个缓存属性,或者通过设置页的类定义中的属性(attribute)进行设置。
用户控件缓存配置设置:通过设置用户控件文件中的@OutputCache指令,或设置控件类定义中的PartialCachingAttribute属性,可以对用户控件缓存进行配置。
2 ASP.NET 页面缓存
ASP.NET可以缓存ASP.NET页所生成的部分响应或所有响应,在ASP.NET中将这种技术称为页面缓存。
说明:页面缓存技术包括如何配置声明和如何编程设置,页面可以设置缓存的过期时间,以及检查缓存页的有效性。同时,页面缓存可以缓存页面的版本以及缓存页面的不同部分。
(1) 声明页面缓存
可以通过两种方式声明页面缓存,一种方式是在每个页面中直接声明,另一种方式是在配置文件中定义缓存的配置属性,然后在每个页面设定该属性。
使用在页面直接声明的方式声明页面缓存的时候,需要在页中包含@OutputCache指令,并定义Duration和VaryByParam属性。在@OutputCache指令中包含Location属性,并将其值定义为OutputCacheLocation枚举中的下列值之一:Any、Client、Downstream、Server、ServerAndClient或None。下面的代码演示如何将页的可缓存性设置为60秒:
<%@ OutputCache Duration="60" VaryByParam="None" %>
另一种凡是是通过配置文件声明为统一的缓存策略,然后在每个页面再分别继承。在应用程序的配置文件web.config中定义缓存配置文件,在配置文件中包括duration和varyByParam设置,如以下代码所示:
<caching>
 <outputCacheSettings>
  <outputCacheProfiles>
   <add name="DemoTest" duration="30" varyByParam="none" />
  </outputCacheProfiles>
 </outputCacheSettings>
</caching>
在使用配置文件的每个ASP.NET页中的包含@OutputCache指令,并将CacheProfile属性设置为web.config文件中定义的缓存配置文件的名称:
<%@ OutputCache CacheProfile="DemoTest" %>
(2) 编程设置页面可缓存性
可以通过编程的方式设置页面的可缓存性,如果应用程序是在运行时进行缓存设定的,可以参考下面的编程方式进行设定。在页面的代码中,调用Response对象的Cache属性的SetCacheability方法。
Response.Cache.SetCacheability(HttpCacheability.Public);
(3) 设置页面缓存过期时间
在ASP.NET中,如果想设置页面缓存的过期时间,可以通过声明的方式和编程的方式来进行设定。
技巧:通过声明方式设置页面的缓存过期时间,需要将@OutputCache指令包括在要缓存其响应的ASP.NET页中。将Duration属性设置为一个正数值,将VaryByParam属性设置为一个值。
技巧:通过编程方式进行设定,可以在页面的后台代码中,通过Response对象的Cache属性设置该页的到期策略,如以下代码所示:
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
(4) 缓存页有效性检查
用户请求缓存页时,ASP.NET根据该页中定义的缓存策略来确定缓存输出是否仍然有效。如果缓存输出有效,则将输出发送到客户端,并且不重新处理该页。ASP.NET提供了使用验证回调在该验证检查期间运行代码的功能,可以编写自定义逻辑来检查该页是否有效。利用验证回调,可以使在使用缓存依赖项的正常进程之外的缓存页无效。下面的例子中,演示了如何实现这种方式的有效性检查过程:
protected void Page_Load(object sender, EventArgs e)
{
 //添加回调缓存
 Response.Cache.AddValidationCallback(new HttpCacheValidateHandler(ValidateCacheOutput), null);
}
public static void ValidateCacheOutput(HttpContext context, Object data, ref HttpValidationStatus status){
 //判断请求中是否包含Status对象
 if(context.Request.QueryString["Status"] != null){
  //取出Status对象的值
  string pageStatus=context.Request.QueryString["Status"];
  //判断Status值的内容是否为invalid
  if(pageStatus=="invalid")
   status=HttpValidationStatus.Invalid;
  //判断Status值的内容是否为ignore
  else if(pageStatus=="ignore")
   status=HttpValidationStatus.IgnoreThisRequest;
  else
   status=HttpValidationStatus.Valid;
 }
 //如果不存在Status值,则显示不正确
 else
  status=HttpValidationStatus.Valid;
}
(5) 缓存页面版本
在实际的开发中,会基于请求为该页创建不同的版本。例如,根据查询字符串中传递的值,该页可能具有不同的输出。ASP.NET允许在输出缓存中缓存同一页的多个版本。输出缓存可能会因下面的几个因素而异:初始请求中的查询字符串、回送时传递的控制值、随请求传递的HTTP标头、发出请求的浏览器的主版本号。
技巧:可以通过以下两种方法来缓存页输出的多个版本:使用@OutputCache指令属性的声明方式,或者使用HttpCachePolicy类的编程方式。
@OutputCache指令包括4个可用来缓存页输出的多个版本的属性:
VaryByParam属性可用来使缓存输出因查询字符串而异的缓存情况。使用示例如下所示:
<%@ OutputCache Duration="60" VaryByParam="Param1" %>
VaryByControl属性可用来使缓存输出因控制值而异的缓存情况。使用示例如下所示:
<%@ OutputCache Duration="60" VaryByControl="Label1;Label2;Label3" %>
VaryByHeader属性可用来使缓存输出因请求的HTTP标头而异的缓存情况。使用示例如下所示:
<%@ OutputCache Duration="60" VaryByParam="None" VaryByHeader="Accept-Language" %>
VaryByCustom属性可用来使缓存牲畜因浏览器类型或定义的自定义字符串而异的缓存情况。使用示例如下所示:
<%@ OutputCache Duration="60" VaryByParam="None" VaryByCustom="browser" %>
3 缓存应用程序数据
ASP.NET提供了一个强大的、便于使用的缓存机制,用于将需要大量服务器资源来创建的对象存储在内存中。缓存这些类型的资源会大大改进应用程序的性能。
说明:缓存是由Cache类实现的,缓存实例是每个应用程序专用的。缓存生存期依赖于应用程序的生存期,重新启动应用程序后,将重新创建Cache对象。
(1) 缓存项的添加
可以通过多种方式实现缓存项的添加,这些方式包括:
通过键和值直接设置项,向缓存添加项。
使用Insert方法向缓存添加项。
向缓存添加项并添加依赖项,以便当该依赖项更改时,将该项从缓存中移除。可以基于其他缓存项、文件和多个对象设置以来项。
将没有过期策略的项添加到缓存中。
向缓存添加项,并定义缓存的项的相对优先级。
通过调用Add方法添加项。
通过键和值的方式,直接添加缓存项,添加的示例代码如下所示:
Cache["Test1"]="Test1";
使用Insert方法,向缓存对象中添加缓存项,示例代码如下所示:
Cache.Insert("Test2","Test2");
向缓存添加项并添加依赖项,示例代码如下所示:
string[] dependencies={"Test2"};
Cache.Insert("Test3","Test3",new System.Web.Caching.CacheDependency(null,dependencies));
添加有过期策略的缓存项,示例代码如下所示:
Cache.Insert("Test4","Test4",null,DateTime.Now.AddMinutes(1d),System.Web.Caching.Cache.NoSlidingExpiration);
添加有优先级的缓存项,示例代码如下所示:
Cache.Insert("Test5","Test5",null,System.Web.Caching.Cache.NoAbsoluteExpiration,
  System.Web.Caching.Cache.NoSlidingExpiration,System.Web.Caching.CacheItemPriority.High,null);
通过调用Add方法添加缓存项,示例代码如下所示:
string Test6=(string)Cache.Add("Test6","Test6",null,System.Web.Caching.Cache.NoAbsoluteExpiration,
  System.Web.Caching.Cache.NoSlidingExpiration,System.Web.Caching.Cache.CacheItemPriority.Default,null);
(2) 缓存项的检索
说明:从缓存中检索缓存项,应指定存储缓存项的键。由于缓存中所存储的信息为易失信息,即该信息可能由ASP.NET移除,因此在检索缓存项的时候,需要先判断该键值对应的缓存项是否存在,再进行检索。
下面的代码示例演示了如何确定名为CacheItem的项是否包含在缓存中。如果在,则代码会将该项的内容分配给名为cachedString的变量。如果该项不在缓存中,则代码会将它添加到缓存中,然后将它分配给cachedString。示例代码如下:
string cachedString;
//判断CacheItem缓存是否为空
if(Cache["CacheItem"]!=null)
{
 //获取CacheItem值的缓存内容
 cachedString=(string)Cache["CacheItem"];
}
else
{
 //添加CacheItem缓存值
 Cache.Insert("CacheItem","Hello,World.");
 cachedString=(string)Cache["CacheItem"];
}
(3) 缓存项的删除
ASP.NET缓存中的数据是易失的,即不能永久保存。缓存自动移除的原因可能是因为缓存已满、该项已过期或者依赖项发生更改。
技巧:除了允许从缓存中自动移除项之外,还可以显式移除项。如果要显示的删除指定键值的缓存项,可以通过调用Remove方法,以传递要移除的项的键。示例代码如下所示:
Cache.Remove("Test1");
4 缓存项操作示例
对应的源视图控件的HTML代码如下所示:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AddCache.aspx.cs" Inherits="AddCache" %>

<!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 runat="server">
    <title>无标题页</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="直接设定Cache" />&nbsp;<asp:Button
            ID="Button8" runat="server" OnClick="Button8_Click" Text="移除" /><br />
        <asp:Button ID="Button2" runat="server" OnClick="Button2_Click" Text="Insert设定Cache" />
        <asp:Button ID="Button9" runat="server" OnClick="Button9_Click" Text="移除" /><br />
        <asp:Button ID="Button3" runat="server" OnClick="Button3_Click" Text="设定Cache依赖项为其他Cache项" />
        <asp:Button ID="Button10" runat="server" OnClick="Button10_Click" Text="移除" /><br />
        <asp:Button ID="Button4" runat="server" Text="设定Cache依赖项为文件" OnClick="Button4_Click" />&nbsp;<asp:Button
            ID="Button11" runat="server" OnClick="Button11_Click" Text="移除" /><br />
        <asp:Button ID="Button6" runat="server" OnClick="Button6_Click" Text="添加有过期设置的缓存" />&nbsp;<asp:Button
            ID="Button12" runat="server" OnClick="Button12_Click" Text="移除" /><br />
        <asp:Button ID="Button5" runat="server" OnClick="Button5_Click" Text="添加有优先级的缓存项" />
        <asp:Button ID="Button13" runat="server" OnClick="Button13_Click" Text="移除" /><br />
        <br />
        <br />
        <asp:Button ID="Button7" runat="server" OnClick="Button7_Click" Text="获取缓存项" />
        <br />
        <br />
        <asp:Label ID="Label1" runat="server"></asp:Label></div>
    </form>
</body>
</html>
在页面的后台中,添加对各个按钮控件的事件:
//直接设定Cache按钮事件
    protected void Button1_Click(object sender, EventArgs e)
    {
        Cache["Mode1"] = "直接设定Cache";
    }
    //移除该缓存按钮事件
    protected void Button8_Click(object sender, EventArgs e)
    {
        Cache.Remove("Mode1");
    }

    //通过Insert方法设定Cache按钮事件
    protected void Button2_Click(object sender, EventArgs e)
    {
        Cache.Insert("Mode2", "Insert设定Cache");
    }
    //移除该缓存按钮事件
    protected void Button9_Click(object sender, EventArgs e)
    {
        Cache.Remove("Mode2");       
    }

    //添加依赖于Mode2缓存项的缓存项Mode3
    protected void Button3_Click(object sender, EventArgs e)
    {
        string[] dependencies = { "Mode2" };
        Cache.Insert("Mode3", "Mode2",
            new System.Web.Caching.CacheDependency(null, dependencies));
    }
    //移除该缓存按钮事件
    protected void Button10_Click(object sender, EventArgs e)
    {
        Cache.Remove("Mode3"); 
    }

    //添加依赖于文件XMLFile.xml的缓存项
    protected void Button4_Click(object sender, EventArgs e)
    {
        Cache.Insert("Mode4", "文件缓存依赖项",
        new System.Web.Caching.CacheDependency(Server.MapPath("XMLFile.xml")));
    }
    //移除该缓存按钮事件
    protected void Button11_Click(object sender, EventArgs e)
    {
        Cache.Remove("Mode4"); 
    }

    //设定有过期设置的缓存项
    protected void Button6_Click(object sender, EventArgs e)
    {
        Cache.Insert("Mode5", "有过期时间的缓存项",
        null, System.Web.Caching.Cache.NoAbsoluteExpiration,
        new TimeSpan(0, 10, 0));
    }
    //移除该缓存按钮事件
    protected void Button12_Click(object sender, EventArgs e)
    {
        Cache.Remove("Mode5"); 
    }

    //设置有优先级的缓存项
    protected void Button5_Click(object sender, EventArgs e)
    {
        Cache.Insert("Mode6", "设置优先级的缓存项",
        null, System.Web.Caching.Cache.NoAbsoluteExpiration,
        System.Web.Caching.Cache.NoSlidingExpiration,
        System.Web.Caching.CacheItemPriority.High, null);
    }
    //移除该缓存按钮事件
    protected void Button13_Click(object sender, EventArgs e)
    {
        Cache.Remove("Mode6"); 
    }

    //将页面中所有的缓存项键值信息全部显示出来
    protected void Button7_Click(object sender, EventArgs e)
    {
        StringBuilder sb = new StringBuilder();
        IDictionaryEnumerator CacheEnum = Cache.GetEnumerator();
        while (CacheEnum.MoveNext())
        {
            sb.Append("Cache键--");
            sb.Append(CacheEnum.Key);
            sb.Append("Cache值--");
            sb.Append(CacheEnum.Value);
            sb.Append("<br/>");
        }
        this.Label1.Text = sb.ToString();
    }
由于缓存项Mode4依赖于一个外部文件XMLFile.xml,所以在网站下需要添加一个名称为XMLFile.xml的XML文件,当修改该文件内容的时候,缓存项失败。

posted @ 2010-07-05 10:03  爱国者  阅读(431)  评论(0编辑  收藏  举报