ASP.NET 缓存






4.67/5 (30投票s)
解释 ASP.NET 中的缓存功能

引言
缓存是一种将创建起来耗时的数据存储在内存中的技术。缓存是 ASP.NET 最优秀的功能之一。例如,您可以缓存从复杂查询中获取数据,这些查询需要花费大量时间来检索数据。后续的请求就不需要再从数据库中获取数据了。您可以直接从缓存中获取数据。通过使用缓存,您可以提高应用程序的性能。
缓存主要有两种类型
- 输出缓存
- 数据缓存
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
委托事件用于此目的。