本文转自http://www.cnblogs.com/stg609/archive/2009/03/22/1418992.html

缓存的作用
      你买电脑的时候,是否会在意CPU的二级缓存?是不是希望二级缓存能够大点?那你有没有想过你为什么会有这种想法?说到底,就是为了性能问题,如果缓存大点,那就意味着我们处理数据的响应速度会更快。这就好比我们查字典,如果有一个单词,你需要知道它的意思,你是不是需要翻开字典,查找目录,翻到指定的页,找到你要的单词,这才能得到该词的解释?可是不幸的是,你并没有想要去记住这个词,当第二次遇到这个词的时候,你是不是又得重复一遍上述的动作?如果你当时记住这个单词,那是不是马上就能知道这个词的意思了?这是不是很高效?
      缓存的缺点
      如果让你在一个信息无法传达的地方(比如原始森林)呆上几个月,而这几个月中,发生了很多变化,其中之一就是你上次查询的那个单词由于某些特殊的原因,它的解释被更换了。而你显然不知道这个事情,如果此时此刻,让你解释这个单词,你是不是会闹笑话?这是什么原因呢?很简单,因为你的脑海里只保存着上次的解释,而没有及时得到更新。

进入正题(本人并未深入研究,如有不足之处,希望大家不吝赐教)

示例1:
      你希不希望你的动态网站也有一个可以记忆的大脑?可能某些朋友会觉得可笑,“这有必要吗?” 。如果你的网站牵涉到大量的数据交互,而这些数据被更新的频率又不是很高,比如有些提供新闻资讯的站点,可能就只需要在上午9:00前对新闻进行更新,而后就不需要再更改了。那也就是说9点后用户访问所得到的数据都是一样的。但是,因为没有提供缓存的能力,用户的每次访问,仍旧会导致服务器端对数据库的访问,这会不会很影响性能?
      在Asp.net webform中可以通过配置页面指令OutputCache来实现效果。在你的aspx文件的头部加入如下的语句:

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

上述主要有两个属性(要配置缓存至少需要这两个属性):
      Duration用来定义页面被缓存的时间(单位为秒),也就是说在10秒内,重复访问这个页面将得到完全一样的数据。
      VaryByParam表示是否因为接受请求的参数(xxx.aspx?id=1)而改变,如果设置为none,表示不改变。
      这样,一个最简单的缓存效果便可以实现了。

示例2:
      通过上面的例子,相信你已经领略到了缓存的魅力。但是,上面的效果无法根据页面的参数进行缓存,也就是说不管我传什么参数给页面,显示的都是一样的。比如我在10秒内先后访问xxx.aspx?id=1与xxx.aspx?id=2,其显示的效果是一样的。如果希望根据参数进行缓存,只要让VaryByParam="id"就可以了(大小写无关)。这样就会根据id的值不同而分别缓存,相当于缓存了页的多个不同的版本。

示例3:
      如果需要部分不被缓存,可以使用服务器端控件Substitution。操作很简单,只需要将该控件拖动到页面上,然后设置一下其中的MethodName属性就可以了。
      该控件编译成Html后,不带任何标记,就如同是一个占位符。其中显示的是内容是由MethodName所指定的方法。但是该方法有一定的限制:
      1:静态方法。
      2:只接受HttpContext 类型的参数。
      3:必须返回 string 类型的值。
      如:

public static string GetCurrentTime(HttpContext context)
{
    return DateTime.Now.ToString();
}

这样,每次页面刷新后就可以获取当前的时间,而其它数据则是被缓存的。

示例4:
      是不是觉得通过这种办法实现的部分缓存、部分刷新的效果有很多局限。如果需要一种更灵活的方式来实现部分缓存的效果,可以通过用户控件来实现。就是说,我们将需要被缓存的数据单独放置在一个页面中,然后在该页面上按照我们前面几个例子所介绍的方法进行设置。最后把设置好的用户控件拖动到最终的页面上就可以了。另外,OutputCache指令中还有一个Shared属性,设置该属性为true就表示共享该控件的输出缓存。

<%@ OutputCache Duration="10" VaryByParam="CategoryiD" Shared="true"%>

示例5:
      ASP.NET还提供了一种更方便的方法,可以对页面的变量进行缓存。即利用Cache对象。一般用来缓存数据变量,如DataSet。但是,如果数据量比较大的话,建议与硬盘缓存结合起来使用。一般利用Cache对象来保存数据库数据可以比利用OutputCache配置性能更好。但是最好不要用Cache来存放用户的登陆信息之类,因为缓存中的数据随时都有可能被替换出内存(如果你掌握一些关于计算机组成方面的原理,可能会更好理解)。

//从Cache对象中获取相应的dataset
DataSet ds = (DataSet)Cache["data"]; //判断dataset是否为空,如果为空,说明没有在缓存中。
if (ds == null)
{
    SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString);
    conn.Open();
    SqlCommand cmd = new SqlCommand("select * from products where CategoryID = 1", conn);
    SqlDataAdapter sda = new SqlDataAdapter(cmd);
    ds = new DataSet();
    sda.Fill(ds);
    Cache["data"] = ds;//将dataset插入到Cache对象中
} GridView1.DataSource = ds;
GridView1.DataBind();

示例6:
      但是上面方式总有点欠缺,如果当数据改变的时候就自动更新缓存,那不是更好。这可以有两种实现方式,通知和轮询。但是MSDN上介绍“通知”的功能只有在Microsoft SQL Server 2005 的完整版,即非速成 (non-Express) 版中才有提供。而其它版本则只提供了轮询方式,况且我也只会轮询方式,所以就来简单介绍下该方式吧。

要使用轮询方式,需配置数据库,配置的主要任务就是在数据库中建立一张表和一些触发器,在这个表中存放的是我们需要轮询的数据库表对象及其相关信息,触发器自然是用来当所监视的表发生变化的时候执行了。幸好,这一系列操作我们只需要用几句简单的命令就可以解决了。否则的话,我可能就会半途而废了。
      打开Vsiual studio的命令提示窗口,输入:
      aspnet_regsql.exe -S <Server> -U <Username> -P <Password> -ed -d <Database> -et -t <TableName>
      如:aspnet_regsql.exe -S .\msserver -U sa -P sa -ed -d Northwind -et -t products
      如果运行成功,会提示:

为 SQL 缓存依赖项启用该数据库。
.
已完成。
为 SQL 缓存依赖项启用该表。

然后,设置与SqlDependency相关的一些信息(如,轮询时间),这些信息在web.config中进行设置:

<caching>
  <sqlCacheDependency enabled = "true" pollTime = "1000" >
    <databases>
      <add name="Northwind" 
         connectionStringName="NorthwindConnectionString"
         pollTime = "1000" />
    </databases>
  </sqlCacheDependency>
</caching>

其中的name只要求是一个方便记忆的名字(一般就记作数据库的名称),pollTime即是轮询时间(单位:毫秒)。
      [引用MSDN中的一段话:小的 pollTime 值虽然使对数据库的请求次数增加,但能更快的将过时数据从缓存中清除。较大的 pollTime 值虽然减少了对数据库的请求次数,但增加了从后台数据改变到清除相关缓存条目之间的延迟时间。还好,数据库请求只是执行一个简单的存储过程,该存储过程只是从一个简单的记录数少的表返回不多的几行。对您的应用程序试用一些不同的 pollTime 值,从中找出一个可平衡数据库访问和数据过时这两者的理想值。允许的最小 pollTime 值为 500 。]
      connectionStringName即是<connectionStrings>节中所配置的数据库连接名称。如:

 <connectionStrings>
  <add name="NorthwindConnectionString" connectionString="Data Source=1AC425E4D0B74F1\msserver;Initial Catalog=Northwind;Integrated Security=True"
   providerName="System.Data.SqlClient" />
 </connectionStrings>

最后修改OutputCache指令中的Duration为"999999"用来表示无限,再加入一个属性SqlDependency,设置该属的值为"database,tableName"。其中database为Web.config 中 <add> 元素的name 属性中指定的数据库名。以Northwind的products表为例就应该写作:SqlDependency="Northwind:products"。如果有两张表就写作:database:tableName;database2:tableName2。

如果一切配置结束,就可以看效果了。你会发现只有当数据被更新的时候,才会更新缓存。这个效果显然比前面几种方式来得更好,但是也不能过渡的使用这种方式,毕竟轮询还是会负出一些代价的。
      [注,上述配置过程中所涉及到的一些数据库名称、表名称,大小写一定要前后一致,否则可能会编译失败。]

示例打包下载

参考:
      1.苏鹏老师讲的“asp.net2.0缓存与性能”
      2.vs2005入门 之 Substitution [视频]
      3.Asp.net 缓存技术总结
      4.将 ASP.NET 输出缓存与 SQL Server 结合使用
      5.使用 SQL 缓存依赖项

作者:stg609

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

本人博客已经转移到Charley Blog

[转]C#基础回顾:Asp.net 缓存的更多相关文章

  1. 定义 ICache 接口,以及实现默认的 ASP.NET 缓存机制

    本文定义 ICache 接口,以及实现默认的 ASP.NET 缓存机制(即通过 System.Web.Caching.Cache)来缓存,将来也可以通过扩展,替换默认实现. 下面直接贴代码了: ICa ...

  2. Spring Boot 2.x基础教程:EhCache缓存的使用

    上一篇我们学会了如何使用Spring Boot使用进程内缓存在加速数据访问.可能大家会问,那我们在Spring Boot中到底使用了什么缓存呢? 在Spring Boot中通过@EnableCachi ...

  3. [C#] C# 基础回顾 - 匿名方法

    C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...

  4. Javascript基础回顾 之(三) 面向对象

    本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对Javascript的一些基本原理普遍存在这里或者 ...

  5. Javascript基础回顾 之(二) 作用域

    本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对Javascript的一些基本原理普遍存在这里或者 ...

  6. Javascript基础回顾 之(一) 类型

    本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对Javascript的一些基本原理普遍存在这里或者 ...

  7. JavaScript 基础回顾——对象

    JavaScript是基于对象的解释性语言,全部数据都是对象.在 JavaScript 中并没有 class 的概念,但是可以通过对象和类的模拟来实现面向对象编程. 1.对象 在JavaScript中 ...

  8. 四、Android学习第四天——JAVA基础回顾(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 四.Android学习第四天——JAVA基础回顾 这才学习Android的 ...

  9. asp.net—缓存

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

随机推荐

  1. MFC RadioButton

    添加一组RadioButton 多个radio button,IDC_RADIO1,IDC_RADIO2,IDC_RADIO3 ..将IDC_RADIO1的Group属性选择上,其他不要选Group属 ...

  2. WW_TRANS_I18N_LOCALE”与“WW_TRANS_I18N_LOCALE”属性

    Struts2 i18n国际化(允许用户自行选择语言)转最近在学习struts2,学习资料是李刚著的<struts2权威指南>,这本书写得非常好,非常有学习价值.我在学习过程中,自己跟着做 ...

  3. ***Linux文件夹文件创建、删除、改名

    Linux删除文件夹命令 linux删除目录很简单,很多人还是习惯用rmdir,不过一旦目录非空,就陷入深深的苦恼之中,现在使用rm -rf命令即可.直接rm就可以了,不过要加两个参数-rf 即:rm ...

  4. HDU 3695 / POJ 3987 Computer Virus on Planet Pandora(AC自动机)(2010 Asia Fuzhou Regional Contest)

    Description Aliens on planet Pandora also write computer programs like us. Their programs only consi ...

  5. Xamarin.Android开发实践(七)

    Xamarin.Android广播接收器与绑定服务 一.前言 学习了前面的活动与服务后,你会发现服务对于活动而言似乎就是透明的,相反活动对于服务也是透明的,所以我们还需要一中机制能够将服务和活动之间架 ...

  6. wp8 --退出程序

    重写OnBackKeyPress事件,设置 e.cancel=true:然后加弹窗代码,为确定按钮订阅事件委托,委托方法里加Application.Current.Terminate();退出方法即可

  7. GridView块布局

    <GridView android:id="@+id/gridview" android:layout_width="match_parent" andr ...

  8. 通过Jmeter完成WebTours的性能测试

    通过BadBoy录制WebTours登录操作: 由此可以看出,BadBoy录制的脚本,结构非常清晰 然后做回放操作: 这是由于关联的原因,导致回放失败

  9. How Many Trees?[HDU1130]

    How Many Trees? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  10. BZOJ4032 : [HEOI2015]最短不公共子串

    第一问: 对B串建立SAM,暴力枚举A的每个子串,在SAM上走,若失配则可行. 第二问: 设g[i][j]表示B串的第i个字符之后最早出现的字符j的位置,暴力枚举A的每个子串,按照g贪心地走,若失配则 ...