(一)什么是缓存

缓存是指临时数据或者文件交换区。比方说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. FusionCharts简单教程(七)-----使用FusionCharts实现下钻功能

          前面介绍的FusionCharts都是对FusionCharts的基本属性进行操作,下面几篇博文就FusionCharts的高级特性做一个介绍,包括:添加下钻链接.使用Style样式定制图 ...

  2. 用curl向指定地址POST一个JSON格式的数据

    昨天的一个任务,用POST 方式向一个指定的URL推送数据.以前都用的数组来完成这个工作. 现在要求用json格式.感觉应该是一样的.开写. <?php $post_url = "ht ...

  3. .NET学习笔记 -- 那堆名词到底是啥(CLR、CLI、CTS、CLS、IL、JIT)

    什么是CLR? CLR,公共语言运行时(Common Language Runtime)是一个由多种语言使用的“运行时”.他的核心功能包括(内存管理.程序集加载.安全性.异常处理和线程同步),可以被面 ...

  4. mac命令

    mac下卸载nodesudo rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,share/man/*/node.*}xc ...

  5. 谨慎DateTime.Now在EF的query中的使用

    执行如下代码: var query = from tr in _carrierRepository select new BaseCarrier { CarrierCode = tr.CarrierC ...

  6. js里cookie操作

    原生js操作cookie 创建和存储 cookie 在这个例子中我们要创建一个存储访问者名字的 cookie.当访问者首次访问网站时,他们会被要求填写姓名.名字会存储于 cookie 中.当访问者再次 ...

  7. iOS-数据持久化-第三方框架FMDB的使用

    FMDB简单介绍 一.简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来更加面向对象,省去了 ...

  8. mysql修改密码

    mysql修改password >mysqladmin -u root -p password newpassword 就这么简单

  9. js const

    js const const 声明创建一个只读的常量.这不意味着常量指向的值不可变,而是变量标识符的值只能赋值一次. const state = { notes: [], activeNote: {} ...

  10. MongoDB修改器总结

    1"$set":用来制定一个字段值,若不存在,则创建:    一般用于点加一个字段   db.users.update({name:"joe"},{" ...