ASP.NET - 数据缓存

什么是缓存?

缓存是一种将经常使用的数据/信息存储在内存中的技术,以便下次需要相同的数据/信息时,可以直接从内存中检索,而不是由应用程序生成。

缓存对于 ASP.NET 中的性能提升极其重要,因为页面和控件是在此处动态生成的。 这对于数据相关的事务尤其重要,因为这些事务的响应时间非常昂贵。

缓存将经常使用的数据放置在快速访问的介质中,例如计算机的随机存取存储器。 ASP.NET 运行时包含一个称为缓存的 CLR 对象的键值映射。 它驻留在应用程序中,可通过 HttpContext 和 System.Web.UI.Page 获得。

在某些方面,缓存类似于存储状态对象。 但是,状态对象中的存储信息是确定性的,即您可以依赖存储在那里的数据,而数据的缓存是不确定性的。

以下情况下数据将不可用:

  • 如果其生命周期到期,
  • 如果应用程序释放其内存,
  • 如果由于某种原因没有进行缓存。

您可以使用索引器访问缓存中的项目,并且可以控制缓存中对象的生命周期并在缓存对象与其物理源之间设置链接。

ASP.Net 中的缓存

ASP.NET 提供以下不同类型的缓存:

  • 输出缓存:输出缓存存储最终渲染的 HTML 页面或发送到客户端的部分页面的副本。 当下一个客户端请求此页面时,不会重新生成页面,而是发送页面的缓存副本,从而节省时间。

  • 数据缓存:数据缓存是指缓存来自数据源的数据。 只要缓存没有过期,对数据的请求就会从缓存中得到满足。 当缓存过期时,从数据源获取新鲜数据并重新填充缓存。

  • 对象缓存:对象缓存是缓存页面上的对象,例如数据绑定控件。 缓存数据存储在服务器内存中。

  • 类缓存:首次运行时,网页或 Web 服务将编译为程序集中的页面类。 然后该程序集被缓存在服务器中。 下次对页面或服务发出请求时,将引用缓存的程序集。 当源代码更改时,CLR 会重新编译程序集。

  • 配置缓存:应用程序范围的配置信息存储在配置文件中。 配置缓存将配置信息存储在服务器内存中。

在本教程中,我们将考虑输出缓存、数据缓存和对象缓存。

输出缓存

渲染页面可能涉及一些复杂的过程,例如数据库访问、渲染复杂的控件等。输出缓存允许通过在内存中缓存数据来绕过与服务器的往返。 甚至整个页面都可以被缓存。

OutputCache 指令负责输出缓存。 它启用输出缓存并对其行为提供一定的控制。

OutputCache 指令的语法:

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

将此指令放在页面指令下。 这告诉环境将页面缓存 15 秒。 以下用于页面加载的事件处理程序将有助于测试页面是否确实被缓存。

protected void Page_Load(object sender, EventArgs e)
{
   Thread.Sleep(10000);  
   Response.Write("This page was generated and cache at:" +
   DateTime.Now.ToString());
}

Thread.Sleep() 方法将进程线程停止指定的时间。 在这个例子中,线程停止了10秒,所以当页面第一次加载时,需要10秒。 但是,下次刷新页面时不会花费任何时间,因为页面是从缓存中检索的,而没有加载。

OutputCache 指令具有以下属性,有助于控制输出缓存的行为:

属性 描述
DiskCacheable true/false 指定输出可以写入基于磁盘的缓存。
NoStore true/false 指定是否发送"no store"缓存控制标头。
CacheProfile String name 要存储在 web.config 中的缓存配置文件的名称。
VaryByParam

None

*

Param- name
分号分隔的字符串列表指定 GET 请求中的查询字符串值或 POST 请求中的变量。
VaryByHeader

*

Header names

分号分隔的字符串列表指定客户端可能提交的标头。
VaryByCustom

Browser

Custom string

告诉 ASP.NET 通过浏览器名称和版本或自定义字符串来改变输出缓存。
Location

Any

Client

Downstream

Server

None

Any:页面可以缓存在任何地方。

Client:缓存内容保留在浏览器中。

Downstream:存储在下游和服务器中的缓存内容。

Server:仅保存在服务器上的缓存内容。

None:禁用缓存。

Duration Number 缓存页面或控件的秒数。

让我们向前面的示例添加一个文本框和一个按钮,并为该按钮添加此事件处理程序。

protected void btnmagic_Click(object sender, EventArgs e)
{
   Response.Write("<br><br>");
   Response.Write("<h2> Hello, " + this.txtname.Text + "</h2>");
}

更改 OutputCache 指令:

<%@ OutputCache Duration="60" VaryByParam="txtname" %>

当程序执行时,ASP.NET 根据文本框中的名称缓存页面。

数据缓存

数据缓存的主要方面是缓存数据源控件。 我们已经讨论过数据源控件表示数据源中的数据,例如数据库或 XML 文件。 这些控件派生自抽象类 DataSourceControl,并具有以下用于实现缓存的继承属性:

  • CacheDuration - 它设置数据源缓存数据的秒数。

  • CacheExpirationPolicy - 它定义缓存中的数据过期时的缓存行为。

  • CacheKeyDependency - 它标识控件的键,该控件在删除后会自动使缓存内容过期。

  • EnableCaching - 指定是否缓存数据。

示例

要演示数据缓存,请创建一个新网站并在其上添加一个新的 Web 表单。 添加具有数据访问教程中已使用的数据库连接的 SqlDataSource 控件。

在此示例中,向页面添加一个标签,该标签将显示页面的响应时间。

<asp:Label ID="lbltime" runat="server"></asp:Label>

除了标签之外,内容页面与数据访问教程中的相同。 为页面加载事件添加事件处理程序:

protected void Page_Load(object sender, EventArgs e)
{
   lbltime.Text = String.Format("Page posted at: {0}", DateTime.Now.ToLongTimeString());
}

设计的页面应如下所示:

数据缓存

当您第一次执行页面时,没有发生任何不同的情况,标签显示,每次刷新页面时,页面都会重新加载,并且标签上显示的时间也会发生变化。

接下来,将数据源控件的 EnableCaching 属性设置为"true",并将 Cacheduration 属性设置为"60"。 它将实现缓存,缓存每60秒就会过期。

时间戳会随着每次刷新而变化,但是如果您在这 60 秒内更改表中的数据,则在缓存过期之前不会显示。

<asp:SqlDataSource ID = "SqlDataSource1" runat = "server" 
   ConnectionString = "<%$ ConnectionStrings: ASPDotNetStepByStepConnectionString %>" 
   ProviderName = "<%$ ConnectionStrings: ASPDotNetStepByStepConnectionString.ProviderName %>" 
   SelectCommand = "SELECT * FROM [DotNetReferences]"
   EnableCaching = "true" CacheDuration = "60">         
</asp:SqlDataSource>

对象缓存

对象缓存比其他缓存技术提供了更大的灵活性。 您可以使用对象缓存将任何对象放入缓存中。 该对象可以是任何类型 - 数据类型、Web 控件、类、数据集对象等。只需分配新的键名称即可将项目添加到缓存中,如下所示:

Cache["key"] = item;

ASP.NET 还提供了 Insert() 方法,用于将对象插入到缓存中。 该方法有四个重载版本。 让我们看看他们:

重载 描述
Cache.Insert((key, value); 使用键名和值、默认优先级和过期时间将项目插入到缓存中。
Cache.Insert(key, value, dependencies); 使用键、值、默认优先级、过期时间和链接到其他文件或项目的 CacheDependency 名称将项目插入到缓存中,以便在这些更改时缓存项目不再有效。
Cache.Insert(key, value, dependencies, absoluteExpiration, slidingExpiration); 这表明过期策略以及上述问题。
Cache.Insert(key, value, dependencies, absoluteExpiration, slidingExpiration, priority, onRemoveCallback); 这与参数一起还允许您设置缓存项的优先级和委托,该委托指向删除项时要调用的方法。

滑动过期用于在指定时间跨度内未使用某个项目时从缓存中删除该项目。 以下代码片段存储一个滑动过期时间为 10 分钟且没有依赖项的项目。

Cache.Insert("my_item", obj, null, DateTime.MaxValue, TimeSpan.FromMinutes(10));

示例

创建一个仅包含按钮和标签的页面。 在页面加载事件中写入以下代码:

protected void Page_Load(object sender, EventArgs e)
{
   if (this.IsPostBack)
   {
      lblinfo.Text += "Page Posted Back.<br/>";
   }
   else
   {
      lblinfo.Text += "page Created.<br/>";
   }
   
   if (Cache["testitem"] == null)
   {
      lblinfo.Text += "Creating test item.<br/>";
      DateTime testItem = DateTime.Now;
      lblinfo.Text += "Storing test item in cache ";
      lblinfo.Text += "for 30 seconds.<br/>";
      Cache.Insert("testitem", testItem, null, 
      DateTime.Now.AddSeconds(30), TimeSpan.Zero);
   }
   else
   {
      lblinfo.Text += "Retrieving test item.<br/>";
      DateTime testItem = (DateTime)Cache["testitem"];
      lblinfo.Text += "Test item is: " + testItem.ToString();
      lblinfo.Text += "<br/>";
   }
      
   lblinfo.Text += "<br/>";
}

第一次加载页面时,它会显示:

Page Created.
Creating test item.
Storing test item in cache for 30 seconds.

如果您在 30 秒内再次单击该按钮,页面将被回发,但标签控件会从缓存中获取其信息,如下所示:

Page Posted Back.
Retrieving test item.
Test item is: 14-07-2010 01:25:04