ASP.NET 缓存,十一--缓存ASP.NET 页的某些部分

有时候,缓存整个页是不实际的;可能需要为每个请求动态创建页的某些部分。在这些情况下,您可能值得花时间来标识与需要大量的服务器资源来构造的页请求相关联的对象或数据。一旦标识了这些项,您就可以通过在 Web 窗体用户控件中创建这些项将它们从页的其他部分分离出来,然后在一段指定的时间中对这些项进行缓存,以节省服务器资源。这就是通常所说的片段缓存。

这项技术允许您将需要花宝贵的处理器时间来创建的页的某些部分(例如数据库查询)与页的其他部分分离开。您可以选择允许为每个请求动态生成需要较少服务器资源的页的部分。

一旦标识了要缓存的页的部分,并且创建了对这些部分中的每个部分进行封装的用户控件后,您必须确定这些用户控件的缓存策略。当在代码隐藏类中创建用户控件时,您可以使用@ OutputCache 指令以声明方式设置这些策略,或使用 PartialCachingAttribute 类以编程方式设置这些策略。

例如,如果将下面的指令包括在用户控件文件的顶部,则该控件的一个版本将在输出缓存中存储 120 秒。

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

同样,如果使用代码隐藏开发方法开发用户控件,则将以下属性包含在类声明的元数据中时,控件版本将在输出缓存中存储 120 秒。

[C#]
[PartialCaching(120)]
[Visual Basic]
<PartialCaching(120)>

如果使用这些技术中的任何一种,则当请求包含用户控件的页时,将仅缓存用户控件。

注意 如果在页中声明并使用了为输出缓存指定的用户控件,则 ASP.NET 页分析器将根据用户控件的创建方式,对两个对象类型中的一个类型进行实例化。如果以声明方式创建用户控件,会添加 StaticPartialCachingControl 对象;如果使用 LoadControl 方法以编程方式创建用户控件,会添加 PartialCachingControl 对象。因此,当请求页时,如果页没有被缓存,分析器会将对象放入用户控件在页的控件层次结构中所占的逻辑位置。

有关可以在页输出上设置的属性的更多信息,请参见 @ OutputCache 指令的相关文档。有关如何开发用户控件的更多信息,请参见 Web 窗体用户控件

注意 因为可以将用户控件嵌套在页上的其他服务器控件中,所以也可以嵌套已被放入输出缓存的用户控件。这意味着可以将输出缓存指令包括在输出缓存页内的用户控件中,或包括在作为另一个输出缓存用户控件一部分的用户控件中。

使用片段缓存时的常见错误

您可以在已为输出缓存指定的用户控件标记中声明 ID 属性,从而可以针对该用户控件的实例进行编程。但是,为了使代码正常工作,您必须显式验证该用户控件在输出缓存中存在。

例如,如果您以声明方式分配给某用户控件一个 ID (MyUserControl),则可以用所包含 .aspx 文件的代码声明块中的以下代码检查该用户控件是否存在。

[C#]
void Page_Load() {
if (MyUserControl != null)
// Place code manipulating MyUserControl here.
}
[Visual Basic]
Sub Page_Load()
If MyUserControl <> Null Then
' Place code manipulating MyUserControl here.
End If
End Sub

如果编写代码来操作一个包含 @ OutputCache 指令的用户控件,则将出现错误。只为首次请求动态生成已进行输出缓存的用户控件;在指定的时间到期之前,从输出缓存满足所有后面的请求。一旦确定用户控件已经实例化,就可以以编程方式从包含的页中操作用户控件。您可以将此逻辑包括在与该用户控件关联的一个页生存期事件中,例如 Page_Load 事件或 Page_PreRender 事件中。

还应注意当具有输出缓存设置的用户控件存在于也具有输出缓存设置的 Web 窗体页时所发生的情况。如果页输出缓存存储持续时间比用户控件输出缓存存储持续时间长,则页输出缓存存储持续时间对于整个页(包括用户控件)都是有效的。例如,如果页输出缓存设置为 100 秒,而用户控件输出缓存设置为 50 秒,则整个页将在输出缓存中存储 100 秒,而与用户控件较短的时间设置无关。以下示例说明了这一点。

page01.aspx

[C#]
<%@ Page language="C#" %>
<%@ Register tagprefix="myControl" tagname="Time" src="uc01.ascx" %>
<%@ OutputCache duration="100" varybyparam="none" %>
<myControl:Time runat="server" /><br> <br> <br>
This page was most recently generated at:<p>
<% DateTime t = DateTime.Now;
Response.Write(t); %>
[Visual Basic]
<%@ Register tagprefix="myControl" tagname="Time" src="uc01.ascx" %>
<%@ OutputCache duration="100" varybyparam="none" %>
<myControl:Time runat="server" /><br> <br> <br>
This page was most recently generated at:<p>
<% Dim t As DateTime = DateTime.Now
Response.Write(t) %>

uc01.ascx

[C#]
<% @Control language="C#" %>
<% @OutputCache duration="100" varybyparam="none" %>
This user control was most recently generated at:<p>
<% DateTime t = DateTime.Now;
Response.Write(t); %>
[Visual Basic]
<% @OutputCache duration="100" varybyparam="none" %>
This user control was most recently generated at:<p>
<% Dim t As DateTime = DateTime.Now
Response.Write(t) %>

不过,如果页输出缓存存储持续时间比用户控件存储持续时间短,则将一直使用缓存用户输出控件,直到其存储时间到期为止,即使该页的其余部分已为某个请求重新生成。例如,如果页输出缓存设置为 50 秒,而用户控件输出缓存设置为 100 秒,则页的其余部分每到期两次,用户控件就到期一次。下面这个简单的示例说明了这一点。

page02.aspx

[C#]
<%@ Page language="C#" %>
<%@ Register tagprefix="myControl" tagname="Time" src="uc02.ascx" %>
<%@ OutputCache duration="50" varybyparam="none" %>
<myControl:Time runat="server" /><br> <br> <br>
This page was most recently generated at:<p>
<% DateTime t = DateTime.Now;
Response.Write(t); %>
[Visual Basic]
<%@ Register tagprefix="myControl" tagname="Time" src="uc02.ascx" %>
<%@ OutputCache duration="50" varybyparam="none" %>
<myControl:Time runat="server" /><br> <br> <br>
This page was most recently generated at:<p>
<% Dim t As DateTime = DateTime.Now
Response.Write(t) %>

uc02.ascx

[C#]
<% @Control language="C#" %>
<% @OutputCache duration="100" varybyparam="none" %>
This user control was most recently generated at:<p>
<% DateTime t = DateTime.Now;
Response.Write(t); %>
[Visual Basic]
<% @OutputCache duration="100" varybyparam="none" %>
This user control was most recently generated at:<p>
<% Dim t As DateTime = DateTime.Now
Response.Write(t) %>