65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 缓存

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (30投票s)

2009年11月7日

CPOL

6分钟阅读

viewsIcon

168027

downloadIcon

2436

解释 ASP.NET 中的缓存功能

引言

缓存是一种将创建起来耗时的数据存储在内存中的技术。缓存是 ASP.NET 最优秀的功能之一。例如,您可以缓存从复杂查询中获取数据,这些查询需要花费大量时间来检索数据。后续的请求就不需要再从数据库中获取数据了。您可以直接从缓存中获取数据。通过使用缓存,您可以提高应用程序的性能。

缓存主要有两种类型

  1. 输出缓存
  2. 数据缓存

1. 输出缓存

通过使用输出缓存,您可以缓存页面的最终渲染 HTML。当相同的页面再次被请求时,就会提供缓存的页面。ASP.NET 不会启动页面生命周期,也不会执行代码。输出缓存的语法是:

 <%@ OutputCache Duration=”60” VaryByParam=”None”  %> 

Duration 属性设置页面将缓存 60 秒。如果用户首先请求该页面,ASP.NET 会运行页面代码并将渲染的 HTML 发送给用户,同时将其保存到缓存中。如果服务器在 60 秒内收到同一页面的请求,ASP.NET 会自动发送缓存的页面副本。如果服务器在缓存页面过期后收到请求,ASP.NET 会再次运行页面代码,并为接下来的 60 秒创建一个新的 HTML 输出缓存副本。

 <%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
        CodeFile="OutputCachingTest.aspx.cs" 
	Inherits="OutputCachingTest" Title="Untitled Page" %>

 <%@ OutputCache Duration="20" VaryByParam="None" %>

 <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
 
   <div class="title">Output Cache</div>
   Date: <asp:Label ID="lblDate" runat="server" Text="" />
   Time: <asp:Label ID="lblTime" runat="server" Text="" /> 
      
 </asp:Content>
 protected void Page_Load(object sender, EventArgs e)
 {
    lblDate.Text = DateTime.Now.ToShortDateString();
    lblTime.Text = DateTime.Now.ToLongTimeString(); 
 } 

在此示例中,页面将缓存 20 秒。

按查询字符串缓存

在实际场景中,动态页面会根据某些参数更改其内容。如果您的页面通过查询字符串接收信息,您可以根据查询字符串轻松缓存页面的不同副本。VarByParam=”None” 告诉 ASP.NET 存储缓存页面的一个副本。VarByParam=”*” 告诉 ASP.NET 为不同的查询字符串参数存储页面的独立副本。

 <%@ OutputCache Duration="60" VaryByParam="*" %>
 
 <div align="right">
   <a href="OutputCachingTest2.aspx">No Query String</a> | 
   <a href="OutputCachingTest2.aspx?id=1">ID 1</a> | 
   <a href="OutputCachingTest2.aspx?id=2">ID 2</a> | 
   <a href="OutputCachingTest2.aspx?id=3">ID 3</a> |
   <a href="OutputCachingTest2.aspx?id=3&langid=1">ID 3</a>
 </div> 

在示例项目中,我正在查询字符串中传递一个不同的“ID”。ASP.NET 为每个“ID”存储一个独立的副本,这种技术在这种情况下非常有用。但这种技术存在一些问题,即页面接受范围广泛的不同查询字符串。在这种情况下,ASP.NET 会根据查询字符串参数缓存页面的独立副本,并可能降低可重用性。在这种情况下,您可以在 VarByParam 属性中指定重要的查询字符串变量名。

 <%@ OutputCache Duration="60" VaryByParam="id;langid" %>

在此情况下,ASP.NET 会缓存与“id”或“langid”不同的独立版本。

自定义缓存

您也可以创建自己的自定义过程来缓存页面。ASP.NET 提供了一种轻松创建自定义缓存的方法。使用 VarByCustom 属性指定代表您正在创建的自定义缓存类型的名称。

 <%@ OutputCache Duration="20" VaryByParam="None" VaryByCustom="browser" %>

您还需要创建一个生成自定义缓存字符串的方法。该方法的语法是:

 public override string GetVaryByCustomString(HttpContext context, string custom)
 { 
    if (custom == "browser")
    {
       return context.Request.Browser.Browser +
              context.Request.Browser.MajorVersion;
    }
    else
    {
       return base.GetVaryByCustomString(context, custom);
    }
 }

此方法必须在 global.asax 文件中编写。此方法返回一个字符串值,ASP.NET 使用此字符串来实现缓存。如果此方法为不同请求返回相同的字符串,ASP.NET 会重用缓存的页面;否则,ASP.NET 会生成一个新的缓存版本。

在我们上面的示例中,GetVaryByCustomString() 根据浏览器名称创建一个缓存字符串。ASP.NET 将为不同的浏览器请求创建不同的缓存版本。

控件缓存

在上述缓存技术中,您可以轻松地缓存整个页面,但如果您想缓存特定控件的内容,可以通过使用 VaryByControl 属性来实现缓存控件的功能。

 <%@ OutputCache Duration="20" VaryByControl="MyControl_1" %>

通过在 .aspx 页面上添加此行,ASP.NET 将缓存 MyControl_1 20 分钟。在此场景中,ASP.NET 创建“MyControl_1”的一个缓存版本,如果缓存尚未过期,ASP.NET 将重用缓存的版本;否则,它会再次执行控件的代码。

如果您想根据某个属性值缓存控件,ASP.NET 也为您提供了此功能。只需在 *.ascx 页面上添加 OutPutCache 指令。

 <%@ Control Language="C#" AutoEventWireup="true" 
	CodeFile="MyControl.ascx.cs" Inherits="Controls_MyControl" %>
 <%@ OutputCache Duration="20" VaryByControl="EmployeeID" %>
 ......
 ...... 

VaryByControl=”EmployeeID” 告诉 ASP.NET 根据控件中声明的 EmployeeID 属性创建控件的不同版本。

.ascx.cs 文件中添加 EmplyeeID 属性,ASP.NET 将使用该属性进行缓存。

 private int _employeeID;

 public int EmployeeID
 {
   get { return _employeeID; }
   set { _employeeID = value; }
 }

 protected void Page_Load(object sender, EventArgs e)
 {
   lblDate.Text = DateTime.Now.ToShortDateString();
   lblTime.Text = DateTime.Now.ToLongTimeString();

   lblEmployeeID.Text = EmployeeID.ToString();

 }

在页面上添加控件并设置 EmployeeID

 <%@ Register Src="Controls/MyControl.ascx" TagName="MyControl" TagPrefix="uc1" %>
 <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
    <div align="center">
        <uc1:MyControl ID="MyControl1" runat="server" EmployeeID="1"></uc1:MyControl>
    </div>
 </asp:Content>

缓存配置文件

ASP.NET 还为您提供了一个在 web.config 中定义缓存设置的功能。假设如果您将缓存设置嵌入到页面中,并且您想将缓存持续时间从 20 秒更改为 30 秒,那么您需要更改所有页面的持续时间。最好将缓存设置保存在 web.config 中,这样您可以轻松管理缓存设置。

<system.web>
  <caching>
    <outputCacheSettings >
      <outputCacheProfiles>
	    <add name ="ProductItemCacheProfile" duration ="60"/>
	  </outputCacheProfiles>
	 </outputCacheSettings>
   </caching>
 </system.web>

现在您可以使用 CacheProfile=”ProfileName” 属性在页面中使用此配置文件。

 <%@ OutputCache CacheProfile ="ProductItemCacheProfile" VaryByParam="None" %>

2. 数据缓存

ASP.NET 还为您提供了一种灵活的数据缓存类型。您可以将创建起来很耗时的项添加到集合对象缓存中。缓存是键值对集合,您可以通过分配新的键名将项添加到缓存集合中。

 Cache["Name"] = data;

此技术不提供对缓存对象的控制。使用 Cache.Insert() 方法,该方法提供五个版本的方法。通过使用 Insert 方法,您可以设置缓存过期策略、优先级、依赖项等。

 date1 = DateTime.Now;
 Cache.Insert("Date1", date1, null, DateTime.Now.AddSeconds(20), TimeSpan.Zero);

ASP.NET 允许您设置绝对过期或滑动过期策略,但您一次只能使用一种。

缓存依赖

您还可以在 ASP.NET 中设置缓存依赖。缓存依赖项允许您使缓存项依赖于另一个资源,以便当该资源更改时,缓存项会被自动删除。CacheDependency 类用于创建依赖项。该类有许多构造函数版本。您可以创建对文件或文件夹的依赖。如果该文件或文件夹发生更改,缓存将过期。您可以依赖其他缓存项。

 date2 = DateTime.Now;

 string[] cacheKeys = { "Date1" };
 CacheDependency cacheDepn = new CacheDependency(null, cacheKeys);
 Cache.Insert("Date2", date2, cacheDepn);

在此示例中,“Date2”缓存对象依赖于“Date1”缓存项。当“Date1”对象过期时,“Date2”将自动过期。在 CacheDependency(null, cacheKeys) 构造函数中,第一个参数是 'null',因为我们没有创建具有文件/文件夹依赖项的缓存。我们只传递了缓存项的键列表,因为我们想创建项缓存依赖项。

回调方法和缓存优先级

ASP.NET 还允许您编写一个回调方法,该方法将在缓存项从缓存中移除时触发。您还可以设置缓存项的优先级。

 protected void Page_Load(object sender, EventArgs e)
 {
   DateTime? date1 = (DateTime?)Cache["Date1"];
   if (!date1.HasValue) // date1 == null
   {
     date1 = DateTime.Now;
     Cache.Insert("Date1", date1, null, DateTime.Now.AddSeconds(20), TimeSpan.Zero, 
                  CacheItemPriority.Default, 
		new CacheItemRemovedCallback(CachedItemRemoveCallBack));
   }

   DateTime? date2 = (DateTime?)Cache["Date2"];
   if (!date2.HasValue) // date2 == null
   {
     date2 = DateTime.Now;
     Cache.Insert("Date2", date2, null, DateTime.Now.AddSeconds(40), TimeSpan.Zero, 
                  CacheItemPriority.Default, 
		new CacheItemRemovedCallback(CachedItemRemoveCallBack));
   }

   // Set values in labels
   lblDate.Text = date1.Value.ToShortDateString();
   lblTime.Text = date1.Value.ToLongTimeString();

   lblDate1.Text = date2.Value.ToShortDateString();
   lblTime1.Text = date2.Value.ToLongTimeString();

 }
    
 private void CachedItemRemoveCallBack(string key, object value, 
				CacheItemRemovedReason reason)
 {
   if (key == "Date1" || key == "Date2")
   { 
      Cache.Remove("Date1");
      Cache.Remove("Date2");
   }
 }

正如您在示例中看到的,我创建了“Date1”和“Date2”缓存。“Date1”的过期持续时间是 20 秒,“Date2”是 40 秒,但您会注意到两者一起过期。原因是的原因是我们注册了移除回调方法。当“Date1”或“Date2”过期时,它会调用 CachedItemRemoveCallBack 方法。在此方法中,我移除了两个缓存项。

ASP.NET 还为您提供了一种处理缓存项更新回调处理程序的功能。CacheItemUpdateCallback 委托事件用于此目的。

参考文献

© . All rights reserved.