System.Web.Caching.Cache类 Asp.Net缓存 各种缓存依赖

Posted kylin2016

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了System.Web.Caching.Cache类 Asp.Net缓存 各种缓存依赖相关的知识,希望对你有一定的参考价值。

Cache类,是一个用于缓存常用信息的类。HttpRuntime.Cache以及HttpContext.Current.Cache都是该类的实例。

一、属性

属性 说明
Count 获取存储在缓存中的项数。
EffectivePercentagePhysicalMemoryLimit 获取在 ASP.NET 开始从缓存中移除项之前应用程序可使用的物理内存百分比。
EffectivePrivateBytesLimit 获取可用于缓存的字节数。
Item 获取或设置指定键处的缓存项。

二、方法

方法名称 说明
Add 将指定项添加到 Cache 对象,该对象具有依赖项、到期和优先级策略以及一个委托(可用于在从 Cache 移除插入项时通知应用程序)。
Get 从 Cache 对象检索指定项。
GetEnumerator 检索用于循环访问包含在缓存中的键设置及其值的字典枚举数。
Insert(String, Object) 向 Cache 对象插入项,该项带有一个缓存键引用其位置,并使用 CacheItemPriority 枚举提供的默认值。
Insert(String, Object, CacheDependency) 向 Cache 中插入具有文件依赖项或键依赖项的对象。
Insert(String, Object, CacheDependency, DateTime, TimeSpan) 向 Cache 中插入具有依赖项和到期策略的对象。
Insert(String, Object, CacheDependency, DateTime, TimeSpan, CacheItemUpdateCallback) 将对象与依赖项、到期策略以及可用于在从缓存中移除项之前通知应用程序的委托一起插入到 Cache 对象中。
Insert(String, Object, CacheDependency, DateTime, TimeSpan, CacheItemPriority, CacheItemRemovedCallback) 向 Cache 对象中插入对象,后者具有依赖项、到期和优先级策略以及一个委托(可用于在从 Cache 移除插入项时通知应用程序)。
Remove 从应用程序的 Cache 对象移除指定项。

 

三、静态字段

名称 说明
NoAbsoluteExpiration  用于 Insert 方法调用中的 absoluteExpiration 参数中以指示项从不到期。 此字段为只读。
NoSlidingExpiration 用作 Insert 或 Add 方法调用中的 slidingExpiration 参数,以禁用可调到期。 此字段为只读。

 

  先来看基本的示例:

  index.aspx.cs页面代码:

 

 

[csharp] view plain copy
 
  1. namespace WebApplication1  
  2. {  
  3.     public partial class _Default : System.Web.UI.Page  
  4.     {  
  5.         protected void Page_Load(object sender, EventArgs e)  
  6.         {  
  7.             Person p = new Person();  
  8.             p.Id = 1;  
  9.             p.Name = "诸葛亮";  
  10.   
  11.             Cache cache = HttpRuntime.Cache;  
  12.             cache.Insert("AA",p);  
  13.             cache.Insert("BB","字符串");  
  14.               
  15.             Response.Write(cache.Get("BB").ToString());     //输出 字符串  
  16.             Person p2 = cache["AA"] as Person;  
  17.             Response.Write(p2.Id + " : " + p2.Name);        //输出 1 : 诸葛亮  
  18.             Response.Write(cache.EffectivePrivateBytesLimit);   //-1 这是一个只读属性,那就没什么好说了,只能输出来看看了,但是-1是什么意思呢?无限吗  
  19.             Response.Write(cache.EffectivePercentagePhysicalMemoryLimit);   //98    开始移除项之前可以使用到98%  
  20.   
  21.   
  22.             Response.Write(cache.Count);        //输出 3  
  23.             Response.Write(cache["BB"]);        //输出 字符串 支持索引器式的读取  
  24.   
  25.             cache.Remove("BB");        //从cache中移除一项  
  26.             Response.Write("~~~" + cache["BB"] + "~~~");    //移除了输出 null,但程序不报错  
  27.   
  28.             foreach (var obj in cache)  
  29.             {  
  30.                 Response.Write(obj.GetType() + "<br/>");    //输出不知道什么鸟东西  
  31.             }  
  32.         }  
  33.     }  
  34.   
  35.     public class Person  
  36.     {  
  37.         public int Id  
  38.         {  
  39.             get;  
  40.             set;  
  41.         }  
  42.   
  43.         public string Name  
  44.         {  
  45.             get;  
  46.             set;  
  47.         }  
  48.     }  
  49. }  

 

 

四、文件缓存依赖

 

  当被依赖的文件更改时,缓存会立即被清空:

  index.aspx.cs代码:

[csharp] view plain copy
 
  1. public partial class _Default : System.Web.UI.Page  
  2.     {  
  3.         protected void Page_Load(object sender, EventArgs e)  
  4.         {  
  5.             Cache cache = HttpContext.Current.Cache;  
  6.             //文件缓存依赖  
  7.             cache.Insert("CC", "依赖项测试", new CacheDependency(@"D:\\123.txt"));  
  8.             //这时候在about.aspx页面添加一行代码,当更改一下D:123.txt时,cache["cc"]会立即被清空  
  9.         }  
  10.     }  


about.aspx.cs代码:

 

[csharp] view plain copy
 
  1. public partial class About : System.Web.UI.Page  
  2.     {  
  3.         protected void Page_Load(object sender, EventArgs e)  
  4.         {  
  5.             //直接打开本页面,输出缓存依赖项测试  
  6.             //当更改D:\\123.txt之后,在刷新,输出空,表明该Cache是依赖于D:\\123.txt的  
  7.             Response.Write(HttpContext.Current.Cache["CC"]);  
  8.         }  
  9.     }  

 

 

五、NoSlidingExpiration 绝对过期时间

  NoSlidingExpiration  绝对过期时间,当超过设定时间,立即移除。

 

  下面来看下绝对过期时间的示例,index.aspx.cs:

[csharp] view plain copy
 
  1. public partial class _Default : System.Web.UI.Page  
  2.     {  
  3.         protected void Page_Load(object sender, EventArgs e)  
  4.         {  
  5.             Cache cache = HttpContext.Current.Cache;  
  6.             //30秒后就到期,立即移除,没商量  
  7.             cache.Insert("DD", "绝对过期测试", null, DateTime.Now.AddSeconds(5), System.Web.Caching.Cache.NoSlidingExpiration);  
  8.         }  
  9.     }  


about.aspx.cs:

[csharp] view plain copy
 
  1. public partial class About : System.Web.UI.Page  
  2.     {  
  3.         protected void Page_Load(object sender, EventArgs e)  
  4.         {  
  5.             //先打开index.aspx添加到缓存 然后立即打开本页面,输出 绝对过期测试  
  6.             //持续刷新5秒后,不会再输出  绝对过期测试  
  7.             Response.Write(HttpContext.Current.Cache["DD"]);  
  8.         }  
  9.     }  

 

六、NoAbsoluteExpiration 滑动过期时间

  NoAbsoluteExpiration  当超过设定时间没再使用时,才移除缓存

  滑动过期测试,index.aspx.cs:

[csharp] view plain copy
 
  1. public partial class _Default : System.Web.UI.Page  
  2.     {  
  3.         protected void Page_Load(object sender, EventArgs e)  
  4.         {  
  5.             Cache cache = HttpContext.Current.Cache;  
  6.             //弹性过期时间,当缓存没使用10秒就过期  
  7.             cache.Insert("DD", "滑动过期测试", null, System.Web.Caching.Cache.NoAbsoluteExpiration,TimeSpan.FromSeconds(10));  
  8.         }  
  9.     }  


about.aspx.cs:

 

[csharp] view plain copy
 
  1. public partial class About : System.Web.UI.Page  
  2.     {  
  3.         protected void Page_Load(object sender, EventArgs e)  
  4.         {  
  5.             //直接打开本页面,输出弹性过期测试  
  6.             //如果一直不停地刷新,都会继续输出,但是当超过10秒后再刷新,不会再输出   滑动缓存测试  
  7.             Response.Write(HttpContext.Current.Cache["DD"]);  
  8.         }  
  9.     }  

注意   当设置绝对到期时间时,请使用 DateTime 结构。当设置弹性过期时间时,请使用 TimeSpan 结构。另外,如果您创建的弹性过期时间小于零或大于一年,则将引发 ArgumentOutOfRangeException 类。

 

 

七、缓存的优先级设置

 

  CacheItemPriority枚举  设置缓存的优先级

[csharp] view plain copy
 
  1. public partial class _Default : System.Web.UI.Page  
  2.     {  
  3.         protected void Page_Load(object sender, EventArgs e)  
  4.         {  
  5.             Cache cache = HttpContext.Current.Cache;  
  6.             //文件权重级别  
  7.             cache.Add("MyData", "缓存重要级别", null, Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(30), CacheItemPriority.High, null);  
  8.         }  
  9.     }  


该枚举一共有六级:

 

[csharp] view plain copy
 
  1. //在服务器释放系统内存时,具有该优先级级别的缓存项最有可能被从缓存删除。  
  2.         Low = 1,//在服务器释放系统内存时,具有该优先级级别的缓存项比分配了 System.Web.Caching.CacheItemPriority.Normal  
  3.         //优先级的项更有可能被从缓存删除。  
  4.         BelowNormal = 2,//在服务器释放系统内存时,具有该优先级级别的缓存项很有可能被从缓存删除,其被删除的可能性仅次于具有 System.Web.Caching.CacheItemPriority.Low  
  5.         Normal = 3,//缓存项优先级的默认值为 System.Web.Caching.CacheItemPriority.Normal。  
  6.         Default = 3,//在服务器释放系统内存时,具有该优先级级别的缓存项被删除的可能性比分配了 System.Web.Caching.CacheItemPriority.Normal  
  7.         //优先级的项要小。  
  8.         AboveNormal = 4,//在服务器释放系统内存时,具有该优先级级别的缓存项最不可能被从缓存删除。  
  9.         High = 5,//在服务器释放系统内存时,具有该优先级级别的缓存项将不会被自动从缓存删除。但是,具有该优先级级别的项会根据项的绝对到期时间或可调整到期时间与其他项一起被移除  
  10.         NotRemovable = 6,  

 

优先级
Low=1
BelowNormal=2
Normal=3
Default=3
AboveNormal=4
High=5
NotRemoveable=6

 

八、当缓存被移除时,通知程序

 

  这时就要用到Add的最后一个参数,委托了:

  index.aspx.cs代码如下:

[csharp] view plain copy
 
  1. public partial class _Default : System.Web.UI.Page  
  2.     {  
  3.         protected void Page_Load(object sender, EventArgs e)  
  4.         {  
  5.             Cache cache = HttpRuntime.Cache;  
  6.             //文件权重级别  
  7.             cache.Add("MyData", "缓冲移除通知", null, DateTime.Now.AddSeconds(10) ,Cache.NoSlidingExpiration,CacheItemPriority.Low, Show);  
  8.         }  
  9.   
  10.         public void Show(string key, object value, CacheItemRemovedReason reason)  
  11.         {  
  12.             Cache cache = HttpRuntime.Cache;  
  13.             Cache.Insert("MyData", "缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!");  
  14.         }  
  15.     }  


about.aspx.cs代码如下:

 

[csharp] view plain copy
 
  1. public partial class About : System.Web.UI.Page  
  2.     {  
  3.         protected void Page_Load(object sender, EventArgs e)  
  4.         {  
  5.             Response.Write(HttpRuntime.Cache["MyData"]);  
  6.         }  
  7.     }  

 

 

  此处实现的效果时:第一次打开index.aspx(让程序加入数据到缓存),然后打开about.aspx显示出“缓存移除通知”,10秒后再刷新,显示

“缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!”  经测试,以上程序的Cache最好还是用HttpRuntime的,否则没有请求时HttpContext会报,“未将对象引用设置到对象的实例”。

  这就是被清空时会自动调用委托程序进行处理,你可以再次将数据添加进入缓存,或者记录到日志等等一系列操作。

九、数据库依赖缓存

  1、配置的方式(sqlserver2000) SqlDependency第一个构造函数。

  首先一个WebForm的Web.Config中的配置文件修改如下:

[csharp] view plain copy
 
  1. <connectionStrings>  
  2.     <add name="ApplicationServices"  
  3.          connectionString="Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;"  
  4.          providerName="System.Data.SqlClient" />  
  5.   </connectionStrings>  
  6.   
  7.   <system.web>  
  8.     <compilation debug="true" targetFramework="4.0" />  
  9.     <caching>  
  10.       <sqlCacheDependency enabled="true" pollTime="1000">  //此行配置的意思是,开启数据库缓存,轮询时间为1秒,这是为了能够快速看到更改效果  
  11.         <databases>  
  12.           <add connectionStringName="ApplicationServices" name="con"/>  
  13.         </databases>  
  14.       </sqlCacheDependency>  
  15.     </caching>  
  16.     </system.web>  


修改Global.asax.cs文件代码如下:

 

[csharp] view plain copy
 
  1. void Application_Start(object sender, EventArgs e)  
  2.         {  
  3.             string connString = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;  
  4.        SqlCacheDependencyAdmin.EnableNotifications(connectionString);     //启动数据库的数据缓存依赖功能                        
  5.        SqlCacheDependencyAdmin.EnableTableForNotifications(connectionString, table);        //启用数据表缓存  
  6.   
  7.         }  


Index.aspx.cs文件代码如下:

 

 

[csharp] view plain copy
 
  1. protected void Page_Load(object sender, EventArgs e)  
  2. {  
  3.     SqlCacheDependency dependency = new SqlCacheDependency("con", "Record");  
  4.     // 新增或修改一条缓存记录  
  5.     HttpRuntime.Cache.Insert("MyData", "数据库缓存测试", dependency);  
  6. }  


About.aspx.cs文件代码如下:

 

 

[csharp] view plain copy
 
  1. protected void Page_Load(object sender, EventArgs e)  
  2. {  
  3.     Response.Write(HttpRuntime.Cache["MyData"]);  
  4. }  


次数实现的效果时,打开Index.aspx.cs文件将数据添加到缓存后,然后打开about.asox,页面输出"数据库缓存测试",这时候更改一下数据库的Record表,再刷新about.aspx页面,上一次输出的内容没有了。

 

 

[csharp] view plain copy
 
  1. System.Data.SqlClient.SqlDependency.Start(connString);  
  2. System.Data.SqlClient.SqlDependency.Stop(connString);  

 

 

  这两行代码不一定要放在Global.asax.cs里面,在代码执行之前和执行之后就OK了。

  注意,在这个例子当中,数据库要开启Service Broker

  检测是否已经启用Service Broker
[csharp] view plain copy
 
  1. Select DATABASEpRoPERTYEX(\'数据库名称\',\'IsBrokerEnabled\')          -- 1 表示已经启用 0 表示没有启用  

 

  启用Servicce Broker
[csharp] view plain copy
 
  1. ALTER DATABASE NX SET ENABLE_BROKER;  

 

如果启动时,一直显示正在执行查询,那么用一下这条语句
[csharp] view plain copy
 
  1. ALTER DATABASE NX SET NEW_BROKER WITH ROLLBACK IMMEDIATE;  
  2. ALTER DATABASE NX SET ENABLE_BROKER;  

 

  2、编程的方式(sqlserver2008),第二个构造函数SqlDependency(sqlcommand sqlcom)

  index.aspx.cs文件代码如下:

[csharp] view plain copy
 
  1. protected void Page_Load(object sender, EventArgs e)  
  2.         {  
  3.             SqlCacheDependency dependency;  
  4.             SqlConnection conn = new SqlConnection(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");  
  5.             using (conn)  
  6.             {  
  7.                 string sql = "select name from dbo.record";  
  8.                 SqlCommand cmd = new SqlCommand(sql, conn);  
  9.                 dependency = new SqlCacheDependency(cmd);  
  10.                 SqlDataAdapter adapter = new SqlDataAdapter(cmd);   //这里要特别注意,你的cmd一定要执行过,或者说Execute过,真正从数据库里面取出过数据  
  11.                 DataSet ds = new DataSet();  
  12.                 adapter.Fill(ds);   //这里才是cmd真正执行的地方,注意真正执行要在绑定dependency之后  
  13.             }  
  14.             Response.Write("开始!");  
  15.             Cache.Insert("MyData", "数据库依赖测试", dependency);  
  16.             Response.Write("完成!");  
  17.         }  


about.aspx.cs代码文件如下:

 

[csharp] view plain copy
 
  1. public partial class About : System.Web.UI.Page  
  2.     {  
  3.         protected void Page_Load(object sender, EventArgs e)  
  4.         {  
  5.             if (HttpRuntime.Cache["MyData"] != null)  
  6.             {  
  7.                 Response.Write(HttpRuntime.Cache["MyData"]);  
  8.             }  
  9.             else  
  10.             {  
  11.                 Response.Write("缓存已不存在!");  
  12.             }  
  13.         }  
  14.     }  

 

 

 

  实现的效果一样是,打开index.aspx文件,再打开about.aspx文件,页面输出"缓存测试结果",当更改表record之后,再刷新about.aspx页面,缓存被清空。

  再来一个例子,上次又是页面啥的,这次用十几行代码说明,这个东东实现的要点:

[csharp] view plain copy
 
  1. static void Main(string[] args)  
  2.         {  
  3.             Cache cache = HttpRuntime.Cache;  
  4.             System.Data.SqlClient.SqlDependency.Start(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");  
  5.   
  6.             // 创建缓存依赖    
  7.             SqlConnection conn = new SqlConnection(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");  
  8.             SqlCommand command = new SqlCommand("select Id,name from dbo.Record", conn);  
  9.   
  10.             SqlCacheDependency dependency = new SqlCacheDependency(command);    //注意,创建的command与SqlCacheDependency绑定要在command执行之前  
  11.             SqlDataAdapter adapter = new SqlDataAdapter(command);     
  12.             DataSet ds = new DataSet();  
  13.             adapter.Fill(ds);    //这里要特别注意,Fill才是真正执行  
  14.               
  15.             cache.Insert("DD", "数据库依赖测试", dependency);  
  16.             Console.WriteLine(cache["DD"]);  
  17.             Thread.Sleep(20000);     //暂停20秒给你更改一下数据库  
  18.             if (cache["DD"] == null)  
  19.             {  
  20.                 Console.WriteLine("数据库已经修改过了!");                 
  21.             }  
  22.             Console.ReadKey();  
  23.             System.Data.SqlClient.SqlDependency.Stop(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");  
  24.         }  

 

  在途中,我会随便修改一下Record表,输出结果如下:

  

  再来一次数据库缓存依赖,回调函数的例子:

[csharp] view plain copy
 
  1. public class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             Cache cache = HttpRuntime.Cache;  
  6.             System.Data.SqlClient.SqlDependency.Start(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");  
  7.   
  8.             // 创建缓存依赖    
  9.             SqlConnection conn = new SqlConnection(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");  
  10.             SqlCommand command = new SqlCommand("select Id,name from dbo.Record", conn);  
  11.   
  12.             SqlCacheDependency dependency = new SqlCacheDependency(command);    //注意,创建的command与SqlCacheDependency绑定要在command执行之前  
  13.             SqlDataAdapter adapter = new SqlDataAdapter(command);     
  14.             DataSet ds = new DataSet();  
  15.             adapter.Fill(ds);    //这里要特别注意,Fill才是真正执行  
  16.   
  17.   
  18.             CacheItemRemovedCallback callback = new CacheItemRemovedCallback(RemovedCallback);  
  19.             cache.Insert("DD", "数据库依赖测试", dependency, DateTime.Now.AddDays(1), TimeSpan.Zero, CacheItemPriority.Default, callback);  
  20.             Console.WriteLine(cache["DD"]);  
  21.             Thread.Sleep(15000);     //暂停15秒给你更改一下数据库  
  22.             if (cache["DD"] == null)  
  23.             {  
  24.                 Console.WriteLine("数据库已经修改过了!");                 
  25.             }  
  26.             Console.ReadKey();  
  27.             System.Data.SqlClient.SqlDependency.Stop(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");  
  28.         }  
  29.   
  30.         public static void RemovedCallback(string key, object value, CacheItemRemovedReason reason)  
  31.         {  
  32.             Console.WriteLine("缓存被移除!");  
  33.             Console.WriteLine(reason.ToString());  
  34.         }  
  35.     }  

 

  输出结果如下:

  

  这里要补充几点:当设置为绝对过期时,后面那个TimeSpan参数要设为TimeSpan.Zero。另外,重载中还有一个方法之前在缓存移除前执行回调函数的,而刚刚那个是缓存数据被移除之后执行的。

  CacheItemUpdateCallback  缓存数据移除之前调用;

    CacheItemRemoceCallback  缓存数据移除之后调用;

  再来写一个:

[csharp] view plain copy
 
  1. public class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             Cache cache = HttpRuntime.Cache;  
  6.             System.Data.SqlClient.SqlDependency.Start(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");  
  7.   
  8.             // 创建缓存依赖    
  9.             SqlConnection conn = new SqlConnection(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");  
  10.             SqlCommand command = new SqlCommand("select Id,name from dbo.Record", conn);  
  11.   
  12.             SqlCacheDependency dependency = new SqlCacheDependency(command);    //注意,创建的command与SqlCacheDependency绑定要在command执行之前  
  13.             SqlDataAdapter adapter = new SqlDataAdapter(command);     
  14.             DataSet ds = new DataSet();  
  15.             adapter.Fill(ds);    //这里要特别注意,Fill才是真正执行  
  16.   
  17.   
  18.             CacheItemUpdateCallback callback = new CacheItemUpdateCallback(RemovedCallback);  
  19.             cache.Insert("DD", "数据库依赖测试", dependency, DateTime.Now.AddDays(1), TimeSpan.Zero, callback);  
  20.             Console.WriteLine(cache["DD"]);  
  21.             Thread.Sleep(15000);     //暂停15秒给你更改一下数据库  
  22.             if (cache["DD"] == null)  
  23.             {  
  24.                 Console.WriteLine("数据库已经修改过了!");                 
  25.             }  
  26.             Console.ReadKey();  
  27.   &nb

    以上是关于System.Web.Caching.Cache类 Asp.Net缓存 各种缓存依赖的主要内容,如果未能解决你的问题,请参考以下文章

    System.Web.Caching.Cache类 缓存 各种缓存依赖(转)

    System.Web.Caching.Cache类 Asp.Net缓存 各种缓存依赖

    缓存处理类(MemoryCache结合文件缓存)

    缓存-System.Web.Caching.Cache

    System.Web.Caching.Cache

    [爬虫学习笔记]MemoryCache缓存的用法学习