(一)什么是缓存

缓存是指临时数据或者文件交换区。比方说CPU上的L1或是L2缓存,内存上被划分出来的缓冲区。我们知道CPU的速度是最快的,其次是内存,最后是硬盘,各个部件之间运算速度有很大的差距,但是各个部件之间又需要交互,由于部件之间运算速度差距大,若是CPU频繁的去访问内存,或者内存频繁的访问硬盘,势必很消耗性能并且效率也很低。若是他们能访问跟自己运算速度差不多的区域,如有必要再由该区域去访问比自己速度更慢的区域(如内存或是硬盘),则能带来更高的性能提升。

(二)为什么Web应用程序需要缓存

这主要是为了减轻Web服务器压力,在客户端提供了缓存机制,当用户访问的网页内容无变化的请求时就会调用缓存中的内容,这样一来减轻了服务器压力,避免无必要的重复操作,使用户网页浏览速度加快,用户体验更好。

(三)缓存依赖

被缓存的文件或者页面发生变化时,cache将会失效。

下面具体介绍各种缓存应用。

(四)WebConfig中配置Cache

在webconfig中caching节点下可以设置整个应用程序是否启用缓存,它优先于页面上的缓存配置,是对整个Web应用程序的整体设置。

1 <system.web>
2 <caching>
3 <outputCache enableOutputCache="false"/>
4 </caching>
5 </system.web>

 

(五)页面中的Cache

在页面的顶部设置如下代码:

<%@ OutputCache Duration="5" VaryByParam="none" %>

即可对整个页面进行缓存,下面对其中的参数做个简单的说明。

  • Duration,以秒为单位的缓存时间。

  • VaryByParam,缓存的内容根据请求参数的不同,缓存多个版本,若有多个参数用分号(;)分割。

  • VarByControl,根据用户控件中服务器控件ID缓存多个版本。

  • VaryByHeader,根据请求的HTTP头,缓存不同的版本。

下面来看两个例子。

例5.1

页面前台代码:

前台代码

后台不书写任何的代码,我们可以看到该页面被缓存了5秒。

例5.2

页面前台代码:

 1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="CacheProfiles.aspx.cs" Inherits="CacheProfiles" %>
2 <%@ OutputCache CacheProfile="CacheProfiles" VaryByParam="none"%>
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4 <html xmlns="http://www.w3.org/1999/xhtml">
5 <head runat="server">
6 <title></title>
7 </head>
8 <body>
9 <form id="form1" runat="server">
10 <div>
11 <%= DateTime.Now.ToString() %>
12 </div>
13 </form>
14 </body>
15 </html>

在WebConfig文件中配置CacheProfiles,如下:

配置代码

后台不书写任何代码,我们看到这次页面被缓存了10秒,采用这种方式可以单独对某个页面进行缓存的配置,也可以对一些页面进行统一配置,如果要修改只需修改配置文件即可。

 

(六)页面局部Cache

页面局部缓存分为两种,一种是对页面较少的部分进行缓存,我们可以用用户控件来实现;另一种是对页面的大部分缓存,只有少部分需要动态改变,我们可以用缓存后替换。下面分别介绍这两种方式。

6.1用户控件缓存

我们先来创建一个简单的用户控件ascx文件,前台代码如下:

1 <%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" %>
2 <%@ OutputCache Duration="10" VaryByParam="none" %>
3 <span>
4 用户控件时间:<%=DateTime.Now.ToString() %>
5 </span>

没有后台代码,其中设置了过期时间为10秒。我们再来创建一个页面,前台代码如下:

 1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="PartCache.aspx.cs" Inherits="PartCache" %>
2 <%@ Register Src="~/WebUserControl.ascx" tagname="UserControl" TagPrefix="MyControl" %>
3 <%@ OutputCache Duration="20" VaryByParam="none" %>
4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5 <html xmlns="http://www.w3.org/1999/xhtml">
6 <head runat="server">
7 <title></title>
8 </head>
9 <body>
10 <form id="form1" runat="server">
11 <p>本页面时间:<%=DateTime.Now.ToString() %></p>
12 <div>
13 <MyControl:UserControl ID="c" runat="server" />
14 </div>
15 </form>
16 </body>
17 </html>

没有后台代码,页面中缓存过期时间设置为20秒,把用户控件拖拽到该页面中。这里面有个规则,如果页面的缓存时间大于控件的缓存时间,则按照页面的缓存时间为主,与用户控件的缓存时间无关;如果页面的缓存时间小于用户控件的缓存时间,则各走个的缓存时间。

6.2缓存后替换

有两个控件支持该功能一个是Substitution控件,另一个是AdRotator控件,这里只介绍前者。前台代码如下:

前台代码

代码中设置了页面的缓存时间为10秒。后台代码:

后台代码

通过刷新页面我们可以看到Substitution控件中的时间一直在变化,不受页面的缓存控制。

 

(七)基于文件的Cache

下面的两个例子都是把文件缓存了起来,第一个是缓存单个文件,后面一个是缓存多个文件,它们分别使用了不同的方式达到了同一个效果,当被缓存的文件变化或者缓存到期时,Cache将会失效。

例7.1

首先,在网站的根目录下创建一个TextFile.txt的文本文件,随意在文件中添加些内容。然后创建页面,添加前台代码:

 1 <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="CacheFile.aspx.cs" Inherits="_Default" %>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head runat="server">
5 <title></title>
6 </head>
7 <body>
8 <form id="form1" runat="server">
9 <div>
10 <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
11 </div>
12 </form>
13 </body>
14 </html>

添加后台代码:

 1 using System.Web.Caching;
2 protected void Page_Load(object sender, EventArgs e)
3 {
4 string info = HttpRuntime.Cache["Info"] as string;
5 if (info == null)
6 {
7 //得到网站目录下的文本文件路径
8 string path = Server.MapPath("~/TextFile.txt");
9 info = System.IO.File.ReadAllText(path) + DateTime.Now.ToString();
10 //把文本文件的内容加上时间加到缓存中
11 HttpRuntime.Cache.Add("Info", info, new System.Web.Caching.CacheDependency(path),
12 System.Web.Caching.Cache.NoAbsoluteExpiration,
13 new TimeSpan(0, 0, 5), //过期策略设置为5秒
14 System.Web.Caching.CacheItemPriority.Normal,
15 null);//缓存失效时的回调函数
16 /*这里也可以使用Insert方法, 如果使用 Insert 方法向缓存添加项,并且已经存在与现有项同名的项,则缓存中的现有项将被替换。
17 而Add 方法将返回添加到缓存中的对象。另外,如果使用 Add 方法,并且缓存中已经存在与现有项同名的项,则该方法不会替换该项,并且不会引发异常。
18 HttpRuntime.Cache.Insert("Info",info,new System.Web.Caching.CacheDependency(path),
19 System.Web.Caching.Cache.NoAbsoluteExpiration,
20 new TimeSpan(0,0,5),
21 System.Web.Caching.CacheItemPriority.Normal,
22 Callback);
23 */
24 }
25 //把信息输出到label标签中
26 Label1.Text = info;
27 }
28
29 private static void Callback(string key, object value, System.Web.Caching.CacheItemRemovedReason reason)
30 {
31 //缓存过期时的通知函数,缓存失效时添加相关操作
32 }

例7.2

我们再在网站的根目录下创建一个XMLFile.xml的xml文件,随意在文件中添加些内容。然后创建页面,前台代码:

前台代码

后台代码:

后台代码

这个例子关联了两个文件,其中任何一个改变都会引起缓存的失效。

以上这两个例子都实现了文件的缓存,但是有一个显著的不同。对于第一个例子,在缓存到期之前如果刷新了页面则缓存时间累加,也就是说页面不会更改,必须在缓存时间内没有刷新页面,过了缓存时间,缓存才会失效。对于第二个例子,不管在缓存时间内如何刷新页面,只要缓存到期,那么页面就会失效。

 

(八)基于sql的Cache

基于sql的缓存分为两种,一种叫做轮询,一种叫做数据库通知。

  • 轮询:数据库不能通知的时候,应用程序可以主动定期访问数据库,检查数据库是否发生变化。
  • 数据库通知:数据库中的数据发生变化时,主动通知应用程序(该功能只支持sql2005以及以上版本)。这里只介绍前一种。

首先我们新建一个数据库名为Student,并且创建一张STName的表,该表中有两个字段ID和Name,ID为自增行。

然后,在WebConfig中配置相关设置。

先配置缓存相关设置,其中pollTime为轮询间隔单位为毫秒,即多长时间访问一次数据库。

1 <system.web>
2 <caching>
3 <sqlCacheDependency enabled="true" pollTime="5000">
4 <databases>
5 <add connectionStringName="StudentConnectionString" name="Student"/>
6 </databases>
7 </sqlCacheDependency>
8 </caching>
9 </system.web>

再添加连接字符串。

1 <connectionStrings>
2 <add name="StudentConnectionString" connectionString="Data Source=.;Initial Catalog=Student;integrated security=true;" providerName="System.Data.SqlClient"/>
3 </connectionStrings>

前台代码:

 1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="SqlCache.aspx.cs" Inherits="SqlCache" %>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head runat="server">
5 <title></title>
6 </head>
7 <body>
8 <form id="form1" runat="server">
9 <div>
10 <asp:GridView ID="GridView1" runat="server">
11 </asp:GridView>
12 <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
13 </div>
14 <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
15 </form>
16 </body>
17 </html>

后台代码:

 1 using System.Data;
2 using System.Data.SqlClient;
3 using System.Configuration;
4 using System.Web.Caching;
5
6 protected void Page_Load(object sender, EventArgs e)
7 {
8 //判断缓存中是否存在STName
9 if (HttpRuntime.Cache["STName"] == null)
10 {
11 this.GridView1.DataSource = BindData();
12 this.GridView1.DataBind();
13
14 //启用更改通知
15 SqlCacheDependencyAdmin.EnableNotifications(ConfigurationManager.ConnectionStrings["StudentConnectionString"].ConnectionString);
16 //连接到 SQL Server 数据库并为 SqlCacheDependency 更改通知准备数据库表
17 SqlCacheDependencyAdmin.EnableTableForNotifications(ConfigurationManager.ConnectionStrings["StudentConnectionString"].ConnectionString, "STName");
18 //声明SqlCacheDependency其中构造函数中的这两个参数(Student必需与WebConfig配置的sqlCacheDependency的一致,STName则是缓存的key)
19 System.Web.Caching.SqlCacheDependency dep = new System.Web.Caching.SqlCacheDependency("Student", "STName");
20 //向缓存集合中插入数据
21 HttpRuntime.Cache.Insert("STName", DateTime.Now.ToString(),
22 dep,
23 System.Web.Caching.Cache.NoAbsoluteExpiration,
24 System.Web.Caching.Cache.NoSlidingExpiration,
25 System.Web.Caching.CacheItemPriority.Default,
26 null);
27 //显示缓存STName中的数据
28 string str = HttpRuntime.Cache["STName"] as string;
29 if (str != null)
30 {
31 this.Label1.Text = str;
32 }
33 }
34 else//存在则把缓存数据显示到页面
35 {
36 this.GridView1.DataSource = BindData();
37 this.GridView1.DataBind();
38 string str = HttpRuntime.Cache["STName"] as string;
39 if (str != null)
40 {
41 this.Label1.Text = str;
42 }
43 }
44 }
45
46 protected void Button1_Click(object sender, EventArgs e)
47 {
48 //更新数据库表中的数据
49 UpdateData();
50 string str = HttpRuntime.Cache["STName"] as string;
51 if (str != null)
52 {
53 this.Label1.Text = str;
54 }
55 this.GridView1.DataSource = BindData();
56 this.GridView1.DataBind();
57 }
58
59
60 private SqlConnection returnConnection()
61 {
62 string connstring = System.Configuration.ConfigurationManager.ConnectionStrings["StudentConnectionString"].ConnectionString;
63 SqlConnection conn = new SqlConnection(connstring);
64 return conn;
65 }
66
67 private DataSet BindData()
68 {
69 /* 读出表中的数据*/
70 SqlCommand cmd = new SqlCommand("SELECT * FROM STName", returnConnection());
71 SqlDataAdapter sda = new SqlDataAdapter(cmd);
72 DataSet ds = new DataSet();
73 sda.Fill(ds);
74 return ds;
75 }
76
77 private void UpdateData()
78 {
79 //更新数据
80 SqlConnection con = returnConnection();
81 SqlCommand cmd = new SqlCommand("Update STName set Name='cc'", con);
82 con.Open();
83 cmd.ExecuteNonQuery();
84 con.Close();
85 }

运行后界面:

点击按钮时,更新了Name字段中的值,一个轮询周期内,可以看到时间变了一次。

对于这个例子还有些话要说。当程序执行完上面代码中的SqlCacheDependencyAdmin.EnableTableForNotifications(ConfigurationManager.ConnectionStrings["StudentConnectionString"].ConnectionString, "STName");之后,我们就在数据库中新创建了一张表,如下图:

该表包括了设置表的要监控的字段,还有表是否发生变化的标识,就相当于一个触发器。

另外,代码中对于HttpRuntime.Cache["STName"]的处理,这里没有直接使用像HttpRuntime.Cache["STName"].ToString()代码,对于缓存来说,有可能有外界的原因导致它失效,如果说失效了那HttpRuntime.Cache["STName"]就为空,再访问它的ToString方法就会引发异常。

除了可以对单表进行缓存,也可以对多张表进行缓存,这就会用到AggregateCacheDependency对象,实现方法并不复杂,这里就不再说明。

(九)清除页面缓存

附带一个清除页面缓存的代码,如下:

1 protected void Page_Load(object sender, EventArgs e)
2 {
3 Response.Buffer = true;
4 Response.ExpiresAbsolute = DateTime.Now.AddSeconds(-1);
5 Response.Expires = 0;
6 Response.CacheControl = "no-cache";
7 Response.AddHeader("Pragma", "No-Cache");
8 }

ASP.NET 缓存的更多相关文章

  1. asp.net—缓存

    1.页面缓存 要实现页面输出缓存,只要将一条 OutputCache 指令添加到页面即可. <%@ OutputCache CacheProfile=" " NoStore= ...

  2. [转]C#基础回顾:Asp.net 缓存

    本文转自http://www.cnblogs.com/stg609/archive/2009/03/22/1418992.html 缓存的作用      你买电脑的时候,是否会在意CPU的二级缓存?是 ...

  3. Asp.Net缓存(2)

    缓存页的多个版本 ASP.NET 允许在输出缓存中缓存同一页的多个版本.输出缓存可能会因下列因素而异: 初始请求 (HTTP GET) 中的查询字符串. 回发时传递的控制值(HTTP POST 值). ...

  4. Asp.Net缓存(1)

    知其根本,方能应用.MSDN上的缓存讲解.先看原来讲解. Asp.Net缓存概述 通常,应用程序可以将那些频繁访问的数据,以及那些需要大量处理时间来创建的数据存储在内存中,从而提高性能. 在这些情况下 ...

  5. ASP.NET缓存策略经验谈

    要提升ASP.NET应用程序的性能,最简单.最有效的方式就是使用内建的缓存引擎.虽然也能构建自己的缓存,但由于缓存引擎已提供了如此多的功能,所以完全不必如此麻烦.在很大程度上,ASP.NET开发者在W ...

  6. (转)ASP.NET缓存全解析6:数据库缓存依赖

    ASP.NET缓存全解析文章索引 ASP.NET缓存全解析1:缓存的概述 ASP.NET缓存全解析2:页面输出缓存 ASP.NET缓存全解析3:页面局部缓存 ASP.NET缓存全解析4:应用程序数据缓 ...

  7. ASP.NET缓存 Cache

    缓存介绍 如果每次进入页面的时候都查询数据库生成页面内容的话,如果访问量非常大,则网站性能会非常差,而如果只有第一次访问的时候才查询数据库生成页面内容,以后都直接输出内容,则能提高系统性能,这样无论多 ...

  8. 概述ASP.NET缓存机制

    PetShop之ASP.NET缓存机制 如果对微型计算机硬件系统有足够的了解,那么我们对于Cache这个名词一定是耳熟能详的.在CPU以及主板的芯片中,都引入了这种名为高速缓冲存储器(Cache)的技 ...

  9. (转)ASP.NET缓存概念及其应用浅析

    ASP.NET缓存概念及其应用浅析 ASP.NET缓存是什么呢?ASP.NET缓存有什么样子的特点呢?本文就向你详细介绍ASP.NET缓存的相关情况. ASP.NET缓存概念是什么呢?通常,应用程序可 ...

  10. ASP.NET缓存中Cache过期的三种策略

    原文:ASP.NET缓存中Cache过期的三种策略 我们在页面上添加三个按钮并双击按钮创建事件处理方法,三个按钮使用不同的过期策略添加ASP.NET缓存. <asp:Button ID=&quo ...

随机推荐

  1. ASP.NET-自定义HttpModule与HttpHandler

    在之前的ASP.NET是如何在IIS下工作的这篇文章中介绍了ASP.NET与IIS配合工作的机制,在http请求经过一系列处理后,最后到达ASP.NET管道中,这时,就是Http Modules和Ht ...

  2. NanoProfiler - 适合生产环境的性能监控类库 之 实践ELK篇

    上期回顾 上一期:NanoProfiler - 适合生产环境的性能监控类库 之 大数据篇 上次介绍了NanoProfiler的大数据分析理念,一晃已经时隔一年多了,真是罪过! 有朋友问到何时开源的问题 ...

  3. java 锁2

    并发,其实是多线程才有的场景... java 多线程? 锁? 现在看来,即使已经工作了4.5年,这仍然不是一个简单的问题. 其实java 本身有提供锁的机制. 比如 Object对象的 wait .n ...

  4. navigationController pop的几种方法

    一,popViewControllerAnimated [self.navigationController popViewControllerAnimated:YES]; 二,popToRootVi ...

  5. 项目管理师prince2

    项目管理师prince2 PRINCE2并不适合用于管理商业活动中的日常事物.商业日常事务通常是指组织机构日常运营中需要完成的那些工作.例如,公司it系统的维护,宾馆的房间整理,或者运营公司的客户呼叫 ...

  6. 使用JSSDK集成微信分享遇到的一些坑

    h5项目中需要集成微信分享,以实现自定义标题.描述.图片等功能.结果遇到了很多坑. 准备工作 务必详细阅读微信JS-SDK说明文档 需要后端支持 强烈建议下载使用微信web开发者工具 按文档配置好公众 ...

  7. NodeMCU初探

    对于ESP8266模块,早就想知道如何用其脚本语言, 自己先用的这个模块测试的 首先是先下载需要用到的工具和固件 链接:http://pan.baidu.com/s/1dF5NZ3N 密码:bziq ...

  8. JavaScript对浏览器的URL进行编码、解码

    关于url编码,js有三个函数.有三个解码方法,escape,encodeURI,encodeURIComponent().有三个解码方法,unescapse,decodeURI,decodeURIC ...

  9. mysql创建数据库指定编码uft8

    mysql创建数据库指定编码uft8 CREATE DATABASE IF NOT EXISTS my_db default character set utf8 COLLATE utf8_gener ...

  10. 【原创】高性能网络编程(二):上一个10年,著名的C10K并发连接问题

    1.前言 对于高性能即时通讯技术(或者说互联网编程)比较关注的开发者,对C10K问题(即单机1万个并发连接问题)应该都有所了解."C10K"概念最早由Dan Kegel发布于其个人 ...