System.Web.Caching.Cache类 缓存 各种缓存依赖-阿里云开发者社区

开发者社区> 杰克.陈> 正文

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

简介: 原文:System.Web.Caching.Cache类 缓存 各种缓存依赖   Cache类,是一个用于缓存常用信息的类。HttpRuntime.Cache以及HttpContext.Current.Cache都是该类的实例。
+关注继续查看
原文:System.Web.Caching.Cache类 缓存 各种缓存依赖

  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页面代码:

namespace WebApplication1
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Person p = new Person();
            p.Id = 1;
            p.Name = "诸葛亮";

            Cache cache = HttpRuntime.Cache;
            cache.Insert("AA",p);
            cache.Insert("BB","字符串");
            
            Response.Write(cache.Get("BB").ToString());     //输出 字符串
            Person p2 = cache["AA"] as Person;
            Response.Write(p2.Id + " : " + p2.Name);        //输出 1 : 诸葛亮
            Response.Write(cache.EffectivePrivateBytesLimit);   //-1 这是一个只读属性,那就没什么好说了,只能输出来看看了,但是-1是什么意思呢?无限吗
            Response.Write(cache.EffectivePercentagePhysicalMemoryLimit);   //98    开始移除项之前可以使用到98%


            Response.Write(cache.Count);        //输出 3
            Response.Write(cache["BB"]);        //输出 字符串 支持索引器式的读取

            cache.Remove("BB");        //从cache中移除一项
            Response.Write("~~~" + cache["BB"] + "~~~");    //移除了输出 null,但程序不报错

            foreach (var obj in cache)
            {
                Response.Write(obj.GetType() + "<br/>");    //输出不知道什么鸟东西
            }
        }
    }

    public class Person
    {
        public int Id
        {
            get;
            set;
        }

        public string Name
        {
            get;
            set;
        }
    }
}

四、文件缓存依赖

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

  index.aspx.cs代码:

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

  about.aspx.cs代码:

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

五、NoSlidingExpiration 绝对过期时间

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

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

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

  about.aspx.cs:

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

六、NoAbsoluteExpiration 滑动过期时间

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

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

    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Cache cache = HttpContext.Current.Cache;
            //弹性过期时间,当缓存没使用10秒就过期
            cache.Insert("DD", "滑动过期测试", null, System.Web.Caching.Cache.NoAbsoluteExpiration,TimeSpan.FromSeconds(10));
        }
    }

  about.aspx.cs:

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

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

七、缓存的优先级设置

  CacheItemPriority枚举  设置缓存的优先级

    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Cache cache = HttpContext.Current.Cache;
            //文件权重级别
            cache.Add("MyData", "缓存重要级别", null, Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(30), CacheItemPriority.High, null);
        }
    }

  该枚举一共有六级:

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

 

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

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

  index.aspx.cs代码如下:

    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Cache cache = HttpRuntime.Cache;
            //文件权重级别
            cache.Add("MyData", "缓冲移除通知", null, DateTime.Now.AddSeconds(10) ,Cache.NoSlidingExpiration,CacheItemPriority.Low, Show);
        }

        public void Show(string key, object value, CacheItemRemovedReason reason)
        {
            Cache cache = HttpRuntime.Cache;
            Cache.Insert("MyData", "缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!缓存被清空啦!");
        }
    }

  about.aspx.cs代码如下:

    public partial class About : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write(HttpRuntime.Cache["MyData"]);
        }
    }

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

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

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

九、数据库依赖缓存

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

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

  <connectionStrings>
    <add name="ApplicationServices"
         connectionString="Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;"
         providerName="System.Data.SqlClient" />
  </connectionStrings>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <caching>
      <sqlCacheDependency enabled="true" pollTime="1000">  //此行配置的意思是,开启数据库缓存,轮询时间为1秒,这是为了能够快速看到更改效果
        <databases>
          <add connectionStringName="ApplicationServices" name="con"/>
        </databases>
      </sqlCacheDependency>
    </caching>
    </system.web>

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

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

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

        protected void Page_Load(object sender, EventArgs e)
        {
            SqlCacheDependency dependency = new SqlCacheDependency("con", "Record");
            // 新增或修改一条缓存记录
            HttpRuntime.Cache.Insert("MyData", "数据库缓存测试", dependency);
        }

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

        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write(HttpRuntime.Cache["MyData"]);
        }

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

System.Data.SqlClient.SqlDependency.Start(connString);
System.Data.SqlClient.SqlDependency.Stop(connString);

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

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

  检测是否已经启用Service Broker
Select DATABASEpRoPERTYEX('数据库名称','IsBrokerEnabled')          -- 1 表示已经启用 0 表示没有启用
  启用Servicce Broker
ALTER DATABASE NX SET ENABLE_BROKER;
如果启动时,一直显示正在执行查询,那么用一下这条语句
ALTER DATABASE NX SET NEW_BROKER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE NX SET ENABLE_BROKER;

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

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

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

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

    public partial class About : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (HttpRuntime.Cache["MyData"] != null)
            {
                Response.Write(HttpRuntime.Cache["MyData"]);
            }
            else
            {
                Response.Write("缓存已不存在!");
            }
        }
    }

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

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

        static void Main(string[] args)
        {
            Cache cache = HttpRuntime.Cache;
            System.Data.SqlClient.SqlDependency.Start(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");

            // 创建缓存依赖  
            SqlConnection conn = new SqlConnection(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");
            SqlCommand command = new SqlCommand("select Id,name from dbo.Record", conn);

            SqlCacheDependency dependency = new SqlCacheDependency(command);    //注意,创建的command与SqlCacheDependency绑定要在command执行之前
            SqlDataAdapter adapter = new SqlDataAdapter(command);   
            DataSet ds = new DataSet();
            adapter.Fill(ds);    //这里要特别注意,Fill才是真正执行
            
            cache.Insert("DD", "数据库依赖测试", dependency);
            Console.WriteLine(cache["DD"]);
            Thread.Sleep(20000);     //暂停20秒给你更改一下数据库
            if (cache["DD"] == null)
            {
                Console.WriteLine("数据库已经修改过了!");               
            }
            Console.ReadKey();
            System.Data.SqlClient.SqlDependency.Stop(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");
        }

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

  

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

    public class Program
    {
        static void Main(string[] args)
        {
            Cache cache = HttpRuntime.Cache;
            System.Data.SqlClient.SqlDependency.Start(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");

            // 创建缓存依赖  
            SqlConnection conn = new SqlConnection(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");
            SqlCommand command = new SqlCommand("select Id,name from dbo.Record", conn);

            SqlCacheDependency dependency = new SqlCacheDependency(command);    //注意,创建的command与SqlCacheDependency绑定要在command执行之前
            SqlDataAdapter adapter = new SqlDataAdapter(command);   
            DataSet ds = new DataSet();
            adapter.Fill(ds);    //这里要特别注意,Fill才是真正执行


            CacheItemRemovedCallback callback = new CacheItemRemovedCallback(RemovedCallback);
            cache.Insert("DD", "数据库依赖测试", dependency, DateTime.Now.AddDays(1), TimeSpan.Zero, CacheItemPriority.Default, callback);
            Console.WriteLine(cache["DD"]);
            Thread.Sleep(15000);     //暂停15秒给你更改一下数据库
            if (cache["DD"] == null)
            {
                Console.WriteLine("数据库已经修改过了!");               
            }
            Console.ReadKey();
            System.Data.SqlClient.SqlDependency.Stop(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");
        }

        public static void RemovedCallback(string key, object value, CacheItemRemovedReason reason)
        {
            Console.WriteLine("缓存被移除!");
            Console.WriteLine(reason.ToString());
        }
    }

  输出结果如下:

  

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

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

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

  再来写一个:

    public class Program
    {
        static void Main(string[] args)
        {
            Cache cache = HttpRuntime.Cache;
            System.Data.SqlClient.SqlDependency.Start(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");

            // 创建缓存依赖  
            SqlConnection conn = new SqlConnection(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");
            SqlCommand command = new SqlCommand("select Id,name from dbo.Record", conn);

            SqlCacheDependency dependency = new SqlCacheDependency(command);    //注意,创建的command与SqlCacheDependency绑定要在command执行之前
            SqlDataAdapter adapter = new SqlDataAdapter(command);   
            DataSet ds = new DataSet();
            adapter.Fill(ds);    //这里要特别注意,Fill才是真正执行


            CacheItemUpdateCallback callback = new CacheItemUpdateCallback(RemovedCallback);
            cache.Insert("DD", "数据库依赖测试", dependency, DateTime.Now.AddDays(1), TimeSpan.Zero, callback);
            Console.WriteLine(cache["DD"]);
            Thread.Sleep(15000);     //暂停15秒给你更改一下数据库
            if (cache["DD"] == null)
            {
                Console.WriteLine("数据库已经修改过了!");               
            }
            Console.ReadKey();
            System.Data.SqlClient.SqlDependency.Stop(@"Server=KISSDODOG-PC;Database=Nx;uid=sa;pwd=123;");
        }

        public static void RemovedCallback(string key, CacheItemUpdateReason reason, out object expensiveObject, out CacheDependency dependency, out DateTime absoluteExpiration, out TimeSpan slidingExpiration)
        {
            //   key:要从缓存中移除的项的标识符。
            //   reason:要从缓存中移除项的原因。
            //   expensiveObject:此方法返回时,包含含有更新的缓存项对象。
            //   dependency:此方法返回时,包含定义项对象和文件、缓存键、文件或缓存键的数组或另一个 System.Web.Caching.CacheDependency 对象之间的依赖项的对象。
            //   absoluteExpiration:此方法返回时,包含对象的到期时间。
            //   slidingExpiration:此方法返回时,包含对象的上次访问时间和对象的到期时间之间的时间间隔。
            expensiveObject = null;
            dependency = null;
            absoluteExpiration = DateTime.Now;
            slidingExpiration = TimeSpan.Zero;
            Console.WriteLine("缓存马上被移除!");
            //但是现在还有没有呢?输出试试
            Console.WriteLine(HttpRuntime.Cache["DD"]);
            Console.WriteLine(reason.ToString());
        }
    }

  输出结果为:

  

  看到,在Update这个委托执行时,缓存还是存在的。

  注意:那个SQL语句还是比较严格的,主要要符合以下要求

       a).     必须设置完全限定名称的数据表。即表名前面需要加所有者,如dbo.test。

       b).     必须明确设置所访问数据库列名称,不能使用“*”。

       c).     必须保证不是聚合函数。如COUNT、MAX等。

 

  SQL SERVER 7.0/2000 SQL SERVER 2005
实现机制 轮询 通知传递服务(Service Broker)

是否需要配置启用

需要

不需要,内置支持

数据更改检测

限于表级更改监测

表级、行级更改监测

   很明显,SQL SERVER 2005的缓存机制更加高效。另外,SqlCacheDependency类还特别结合SQL SERVER 2005 进行了优化:

        a).     使用SQL SERVER 2005 时,SqlCacheDependency类支持与System.Data.SqlClient.SqlDependency类进行集成。应用程序可创建SqlDependency对象,并通过OnChanged事件处理程序接受通知进行注册。这样,应用程序不仅可以使用Sql server 2005的查询通知机制来监测使用SQL查询结果无效的数据更改,并将缓存对象从缓存中移除,而且还可以轻松获取数据更改通知,以便刷新缓存。(从这里可以看出,当触发onRemoveCallback委托的时候,数据已经从缓存里面删除了,这样一来可以手动在委托里面添加缓存,或者干脆设置成null,让他下次调用的时候再缓存。)

        b).     不仅向应用程序添加缓存依赖项,还可以与@OutputCache指令一起使用,以生成依赖于SqlServer数据库表的输出缓存的页面或用户控件。对于用户控件,@OutputCache指令不支持使用SQL SERVER 2005 的查询通知(即onRemoveCallback委托)。

十、组合依赖缓存

  当依赖的内容为多个Dependency时,可以通过AggregateCacheDependency创建依赖的组合,以便在任何一个依赖项发生变化时,使缓存项失效。
  组合的缓存依赖内部为一个集合,可以保存多个缓存依赖对象,将这些缓存依赖对象作为一个整体应用在缓存项目上,当其中某一个缓存依赖失效的时候,就可以使缓存的数据被丢弃。

  组合依赖缓存示例:

//创建缓存依赖
System.Web.Caching.SqlCacheDependency product = new System.Web.Caching.SqlCacheDependency("northwindcache","products");
System.Web.Caching.SqlCacheDependency category = new System.Web.Caching.SqlCacheDependency("northwindcache","products")
//多个缓存依赖组合成一个依赖对象使用
System.Web.Caching.AggregateCacheDependency acd = new System.Web.Caching.AggregateCacheDependency();
acd.Add(product,category);

 

十一、System.Web.Caching.Cache Insert和Add方法的区别

   Add方法

object Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);

   Insert方法

void Insert(string key, object value); //永不过期
void Insert(string key, object value, CacheDependency dependencies);  //依赖
void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration);//绝对时间过期:
void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback);  //依赖+回调
void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);  //依赖+优先级+回调

   比较、区别

    a). Insert方法支持5种重载,使用灵活,而Add方法必须提供7个参数;

    b). Add方法可以返回缓存项的数据对象,Insert 返回Void;

    c). 添加重复缓存情况下(Key已存在),Insert会替换该项,而Add方法则不执行任何操作,并返回原来保存的object对象(Update 2014-03-18)。

  过期策略 

    a). 永不过期
      Insert(string key, object value);

    b). 绝对时间过期

      DateTime.Now.AddSeconds(10)表示缓存在10秒后过期,TimeSpan.Zero表示不使用平滑过期策略。

      例:Cache.Insert("Data", ds,null, DateTime.Now.AddSeconds(10), TimeSpan.Zero);

    c). 变化时间过期(平滑过期)

      DateTime.MaxValue表示不使用绝对时间过期策略,TimeSpan.FromSeconds(10)表示缓存连续10秒没有访问就过期。

      例:Cache.Insert("Data", ds, null, DateTime.MaxValue, TimeSpan.FromSeconds(10));

十二、清空缓存

  清空缓存主要通过Remove()方法,但是只能通过传入一个Key,清空一个。

  GetEnumerator()方法用于获取所有缓存项。MoveNext()用于将位置移动到下一个缓存项。

  如果想清空所有缓存,由于Cache类没有提供RemoveAll()方法,所以可以通过以下方式实现:

        IDictionaryEnumerator DicCache = HttpRuntime.Cache.GetEnumerator();
        int count = HttpRuntime.Cache.Count;
        for (int i = 0; i < count; i++)
        {
            DicCache.MoveNext();
            HttpRuntime.Cache.Remove(DicCache.Entry.Key.ToString());
        }

十三、缓存依赖总结

  缓存依赖主要有如下技术点

  Dependency依赖:.Net中支持两种依赖:CacheDependency和SqlDependency(两者都是Dependency的子类)。从.Net2.0开始,CacheDependency不再是密封的,而是可以继承的。
        ┠CacheDependency:表示对文件或者目录的依赖
        ┠SqlDependency:表示基于SQL数据库的依赖

  过期时间:过期时间分绝对过期时间和滑动过期时间两种。
     ┠绝对过期时间:为特定时间点,类型为DateTime,如果不使用绝对过期时间,那么,使用System.Web.Caching.Cache.NoAbsoluteExpiration表示。
     ┠滑动过期时间:为一个事件间隔,类型为TimeSpan,如果不使用滑动过期时间,使用System.Web.Cacheing.NoSlidingExpiration表示。

  删除通知:.Net提供了一个机制,当被缓存的数据从内存中移除的时候,可以提供一个通知机制,来回调用户定义的方法,方法必须符合CacheItemRemoveCallback委托的定义。该委托定义如下:

public delegate void CacheItemRemoveCallback(string key,Object value,CacheItemRemovedReason reason)

  其中,CacheItemRemoveReason为缓存项被移除的原因。CacheItemRemovedReason是一个枚举类型,定义了如下原因:

  1. DependencyChange:由于依赖发生变化被移除;
  2. Expired:由于过期被移除;
  3. Removed:由于调用Insert插入一个同名的缓存项或者调用Remove失效被移除;
  4. Underused:系统移除;

注意:

  • 回调的时机是不可预知的,不能假定回调发生时,回调方法的执行线程存在HttpContext的上下文,为了在没有请求上下文的时候取得对Cache对象的引用,可以通过HttpRuntime的Cache属性来使用应用程序的Cache。
  • 不能在页面上使用实例方法来作为回调方法,当在页面上使用回调方法时,由于指向回调方法的引用会阻止垃圾回收机制,因此会造成内存很快耗光。
  • 一般通过在自定义类的静态方法实现回调方法,或者使用页面对象的静态方法的实现。

PS:  

  1、 CacheDependency是AggregateCacheDependency和SqlCacheDependency的父类。主要用于在应用程序数据缓存对象与文件、缓存键、文件或缓存键的数组或另外一个CacheDependency对象之间建立依赖关系。CacheDependency监视依赖关系比便在任何对象更改时自动移除缓存对象。CacheDependency可以监测一组(到文件或目录的)文件路径的更改情况。

  2、 AggregateCacheDependency主要用于实现聚合缓存依赖。如一笔数据同时对两个表进行缓存依赖,一旦其中任何一个表数据更改缓存将失效。

  3、 SqlCacheDependency将应用程序数据缓存对象、页面输出缓存、数据源控件等与指定SQL Server数据库表或Sql Server 2005 查询结果之间建立缓存依赖关系,在表发生更改(Sql Server 2005 行级别更改)时,自动从缓存中删除和重新添加与该表关联的缓存对象。一般而言:

  • SqlCacheDependency (SqlCommand) 用于SQL SERVER 2005
  • SqlCacheDependency (数据库名, 表名) 用于SQL SERVER 7.0/2000

  有以下几条缓存数据的规则。:
  第一,数据可能会被频繁的被使用,这种数据可以缓存。 
  第二,数据的访问频率非常高,或者一个数据的访问频率不高,但是它的生存周期很长(很少变动),这样的数据最好也缓存起来。 
  第三,是一个常常被忽略的问题,有时候我们缓存了太多数据,通常在一台X86的机子上,如果你要缓存的数据超过800M的话,就会出现内存溢出的错误。所以说缓存是有限的。换名话说,你应该估计缓存集的大小,把缓存集的大小限制在10以内,否则它可能会出问题。在Asp.net中,如果缓存过大的话也会报内存溢出错误,特别是如果缓存大的DataSet对象的时候。

  你应该认真分析你的程序。根据实际情况来看哪里该用,哪里不该用。如:Cache用得过多也会增大服务器的压力。整页输出缓存,又会影响数据的更新。 如果真的需要缓存很大量的数据,可以考虑静态技术。

  CacheDependency还支持【嵌套】,即:CacheDependency的构造函数中支持传入其它的CacheDependency实例,这样可以构成一种非常复杂的树状依赖关系。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Memcached缓存
memcached是应用较广的开源分布式缓存产品之一,它本身其实不提供分布式解决方案。 在服务端,memcached集群环境实际就是一个个memcached服务器的堆积,环境搭建较为简单。 cache的分布式主要是在客户端实现,通过客户端的路由处理来达到分布式解决方案
5 0
Guava Cache缓存设计原理(下)
Guava Cache基于ConcurrentHashMap的设计,在高并发场景支持和线程安全上都有相应改进策略,使用Reference引用命令,提升高并发下的数据访问速度并保持了GC的可回收,有效节省空间。 write链和access链的设计,能更灵活、高效的实现多种类型的缓存清理策略,包括基于容量的清理、基于时间的清理、基于引用的清理等。 编程式的build生成器管理,让使用者有更多的自由度,能够根据不同场景设置合适的模式。 还可以显式清除、统计信息、移除事件的监听器、自动加载等功能。
9 0
使用Nginx反向代理和proxy_cache缓存搭建CDN服务器加快Web访问速度
碰到问题:移动用户访问web服务器www.osyunwei.com很慢解决办法:1、在移动机房放置一台nginx反向代理服务器2、通过域名DNS智能解析,所有移动用户访问www.osyunwei.com时解析到nginx反向代理服务器3、nginx反向代理服务器与web服务器之间采用专线连接系统运维  www.
1632 0
2、web爬虫,scrapy模块以及相关依赖模块安装
当前环境python3.5 ,windows10系统 Linux系统安装 在线安装,会自动安装scrapy模块以及相关依赖模块
824 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
12037 0
Web Service依赖的jar包介绍
This directory includes the CXF jar, the CXF manifest jar, the required dependencies, and many optional dependencies. The "modules" directory contains the cxf.jar split up into smaller pieces if
1581 0
+关注
杰克.陈
一个安静的程序猿~
10427
文章
2
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载