本文转自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. 转MYSQL学习(三) 函数

    这一节主要介绍MYSQL里的函数,MYSQL里的函数很多,我这里主要介绍MYSQL里有而SQLSERVER没有的函数 数学函数 1.求余函数MOD(X,Y) MOD(X,Y)返回x被y除后的余数,MO ...

  2. 9.Python笔记之面向对象高级部分

    类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...

  3. 【USACO】pprime

    开始看第一眼题就觉得问题会在超时上,果然写了个小代码运行到test 9时超时了 #include <stdio.h> #include <math.h> int isprime ...

  4. HDU1568斐波那契推理

    Fibonacci Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  5. Spell checker(poj 1035)

    题意:     此题是一个字符串的问题,首先要给出一个字典,里面存储了数个单词.而后,给出一个单词,如果字典中存在,那么就输出correct,如果字典中没有,那么就要判断是不是这个单词有错误,错误有3 ...

  6. netcat nc

    http://pan.baidu.com/s/1bo2IH9X#netcat 云盘下载 [root@bass ~]# tar -xjvf netcat-0.7.1.tar.bz2 [root@bass ...

  7. php 解决和避免form表单重复提交的方法

    在提交表单的时候,可能遇到网速等导致页面突然加载变慢,用户重复地点击提交按钮,将在数据库产生多条数据,导致不可控情况. 比如下面的情况就会导致表单重复提交: 点击提交按钮两次. 点击刷新按钮. 使用浏 ...

  8. C++学习网站总结(转)

    总结帖: http://club.topsage.com/thread-361504-1-1.html Visual C++ (VC) / MFC 电子书下载: Visual C++ 2008 入门经 ...

  9. JSON浅总

    我们在以前的学习中了解到XML是一种结构化的数据表示方式,一种可扩展标记语言!可以把XML理解成一个微型的结构化的小的数据库,保存一些小型的数据和传输数据,有严格的显示限制.但是XML语句有些冗长和繁 ...

  10. 【HTML5】Canvas画布

    什么是 Canvas? HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像. 画布是一个矩形区域,您可以控制其每一像素. canvas 拥有多种绘制路径.矩形.圆形.字符以 ...