作为ASP.NET的Web开发者,经常需要处理动态内容,这些内容可能来自数据库、服务器目录、XML文件或从其他网站获取。缓存技术意味着将频繁使用的数据存储在内存中,以提高性能。本文将探讨在ASP.NET中缓存的实用性。
设想一个场景,当网页的内容从数据库中提取时,用户根据某些条件请求内容。如果数据库频繁更改,以至于在同一个用户的两次请求之间,预期数据库会发生变化,那么就不能缓存用户请求的数据。但如果数据库不经常更改,可以实施一些缓存,以便如果用户频繁请求相同的数据,不必每次都访问数据库(因为知道内容没有变化)。
这里的两个关键术语是频率和条件。频率是预期用户请求特定页面的次数,条件是决定页面上显示结果的唯一性的因素。
频率很重要,因为需要弄清楚数据库变化的间隔,并将其与用户请求的频率进行比较,以便可以实施缓存,并确保用户不会看到过时的数据。
条件很重要,因为需要确保为页面的每个唯一条件实施缓存。不应该出现用户基于条件01请求内容,而却向他展示条件00的缓存结果(之前为他缓存的)。
有了这些理论基础,让继续看看ASP.NET如何提供缓存功能,而不需要编写大量代码来管理。
在ASP.NET中有两种类型的缓存:
页面输出缓存指的是Web服务器在用户请求后,将某个网页缓存到内存中,以便后续对相同页面的请求会检查缓存页面的有效性,而不会消耗资源(如数据库访问或文件访问),页面将从缓存中返回给用户。
现在问题是,如何确保用户不会看到过时的数据。ASP.NET提供了各种配置选项,让可以编程以确保用户永远不会获得陈旧的数据。
让以一个简单的网页为例,它有一个文本框、一个按钮和一个标签。目前,这个页面没有启用缓存,所以每次回发时,都会向Web服务器发出请求。可以通过在标签中显示当前时间来验证这一点。
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToLongTimeString();
}
现在让通过添加以下声明来启用页面的缓存:
<%@ OutputCache Duration="30" VaryByParam="none" %>
这里说的是这个页面应该被缓存30秒。可以通过按下按钮来验证这一点。30秒内时间字符串不会改变,第二个属性VaryByParam指定缓存不依赖于任何参数,这样做可能导致用户看到过时的数据,比如在案例中,如果在文本框中写入内容并进行回发,它将不断回退到页面缓存时文本框中的旧数据。
因此,一个好的做法是说如果文本框中的数据发生变化,缓存的页面就不再有效,让现在就这样做:
<%@ OutputCache Duration="30" VaryByParam="TextBox1" %>
现在可以看到,只要文本框的内容没有变化,页面输出就会被缓存。如果改变了文本框的内容,服务器就会再次处理页面,然后再次缓存它。
所看到的是,可以指定页面应该被缓存的持续时间,这与之前讨论的频率有关。持续时间应该选择得当,以便在那段时间内不期望数据发生变化,对于条件,看到了如何使用VaryByCustom来确保为每个不同的条件生成输出,并且缓存的副本不仅仅是呈现给用户。
让看看一些其他参数,可以用来定制缓存行为。
如果需要根据不同的查询字符串输出不同的页面,那么可以在这里指定查询字符串参数的列表,或者可以说VaryByParam="*"来对所有查询字符串参数做同样的事情。现在让快速看看如果需要根据查询字符串参数更改缓存页面,需要做什么。
<%@ OutputCache Duration="30" VaryByParam="name" %>
protected void Button2_Click(object sender, EventArgs e)
{
int name;
if (Request.QueryString["name"] == null)
{
name = 1;
}
else
{
name = Convert.ToInt32(Request.QueryString["name"]) + 1;
}
Response.Redirect("varybyqs.aspx?name=" + name.ToString());
}
此外,如果有部分页面缓存(片段缓存)的需求,可以简单地使用需要缓存的控件,并将它们放在一个用户控件中。然后可以使用上面提到的技术在自定义控件中启用缓存行为,就有部分页面缓存了。(查看实现代码。)
注意:上述方法使能够通过在页面上声明来使用缓存。也可以以编程方式控制缓存。
应用程序数据缓存是一种存储缓存中Data对象的机制。它与页面缓存无关。ASP.NET允许以基于键值的缓存存储对象。可以使用它来存储需要被缓存的数据。让继续以同一个例子为例,尝试现在将DateTime对象存储在应用程序缓存中。
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
Cache["time"] = DateTime.Now;
}
Label1.Text = ((DateTime)Cache["time"]).ToLongTimeString();
}
这段代码将DateTime对象存储在应用程序缓存中,并使用缓存中的对象持续显示初始请求的时间。
与应用程序数据缓存相关的各种参数可以用来控制其行为。
注意:源代码包含每种技术的单独页面。单独运行每个页面以查看缓存在行动中。