Asp.Net 基础知识回顾_Cache

1、传统缓存方式html

好比将可重复利用的东西放到Application或是Session中去保存。web

 Session["Count"] = 100;sql

 Application["Count"] = 100;数据库

2、页面输出缓存编程

页面输出缓存是最为简单的缓存机制,该机制将整个ASP.NET页面内容保存在服务器内存中。当用户请求该页面时,系统从内存中输出相关数据,直到缓存数据过时。在这个过程当中,缓存内容直接发送给用户,而没必要再次通过页面处理生命周期。一般状况下,页面输出缓存对于那些包含不须要常常修改内容,须要大量处理才能编译完成的页面特别有用。须要注意的是,页面输出缓存是将页面所有内容都保存在内存中,并用于完成客户端请求。数组

设置页面输出缓存可使用如下两种方式:一种是使用@OutputCache指令,另外一种是使用页面输出缓存API。页面输出缓存API主要是指HttpCachePolicy类。浏览器

@ OutputCache以声明的方式控制 ASP.NET 页或页中包含的用户控件的输出缓存策略。缓存

语法以下:服务器

<%@ OutputCache Duration="#ofseconds"
   Location="Any | Client | Downstream | Server | None | ServerAndClient "
   Shared="True | False"
   VaryByControl="controlname"
   VaryByCustom="browser | customstring"
   VaryByHeader="headers"
   VaryByParam="parametername" 
   CacheProfile="cache profile name | ''"
   NoStore="true | false"
   SqlDependency="database/table name pair | CommandNotification"
%>

Duration网络

页或用户控件进行缓存的时间(以秒计)。在页或用户控件上设置该属性为来自对象的 HTTP 响应创建了一个过时策略,并将自动缓存页或用户控件输出。

Location

用于指定输出缓存项的位置。其属性值是OutputCacheLocation枚举值,它们是Any、Client、Downstream、None、Server和ServerAndClient。默认值是Any,表示输出缓存可用于全部请求,包括客户端浏览器、代理服务器或处理请求的服务器上。须要注意的是,包含在用户控件中的@OutputCache指令不支持此属性。

Shared

一个布尔值,肯定用户控件输出是否能够由多个页共享。默认值为 false。

NoStore

该属性定义一个布尔值,用于决定是否阻止敏感信息的二级存储。须要注意的是,包含在用户控件中的
@OutputCache指令不支持此属性。

SqlDependency

    提供了这样一种能力:当被监测的数据库中的数据发生变化时,SqlDependency会自动触发OnChange事件来通知应用程序,从而达到让系统自动更新数据(或缓存)的目的。

VaryByControl

该属性使用一个分号分隔的字符串列表,来更改用户控件的输出缓存。这些字符串表明在用户控件中声明的ASP.NET服务器控件的ID属性值。除非已经包含了VaryByParam属性,不然在@ OutputCache指令中,该属性是必需的。

VaryByCustom

用于自定义输出缓存要求的任意文本。若是赋予该属性值是browser,缓存将随浏览器名称和主要版本信息的不一样而异。若是输入了自定义字符串,则必须在应用程序的Global.asax文件中重写HttpApplication.GetVaryByCustomString方法。

VaryByHeader

该属性中包含由分号分隔的HTTP标头列表,用于使输出缓存发生变化。当将该属性设为多标头时,对于每一个指定的标头,输出缓存都包含一个请求文档的不一样版本。VaryByHeader属性在全部HTTP 1.1缓存中启用缓存项,而不只限于ASP.NET缓存。用户控件中的@ OutputCache指令不支持此属性。

3、页面输出缓存API

Response类的Cache属性用于获取页面缓存策略,Cache属性的核心是调用System.Web.HttpCachePolicy。主要用于设置缓存特定的HTTP标头的方法和用于控制ASP.NET页面输出缓存的方法。因为HttpCachePolicy类方法众多,下面简要说明几个经常使用方法。

SetExpires

用于设置缓存过时的绝对时间。它的参数是一个DataTime类的实例,表示过时的绝对时间。

SetLastModified

用于设置页面的Last-Modified HTTP标头。Last-Modified HTTP标头表示页面上次修改时间,缓存将依靠它来进行计时。若是违反了缓存限制层次结构,此方法将失败。该方法的参数是一个DataTime类的实例。

SetSlidingExpiration 

该方法将缓存过时从绝对时间设置为可调时间。其参数是一个布尔值。当参数为true时,Cache-Control HTTP标头将随每一个响应而更新。当参数为false时,将保留该设置,且任何启用可调整过时的尝试都将静态失败。此方法不直接映射到HTTP标头,它由后续模块或辅助请求来设置源服务器缓存策略。

SetCacheability

用于设置页面的Cache-Control HTTP标头。该标头用于控制在网络上缓存文档的方式。该方法有两种重载方式,所不一样的是参数。一种重载方法的参数是HttpCacheability枚举值,包括NoCache、Private、Public、Server、ServerAndNoCache和ServerAndPrivate。另外一种方法的参数有两个,一个参数是HttpCacheability枚举值,另外一个参数是字符串,表示添加到标头的缓存控制扩展。须要注意的是,仅当与Private或NoCache指令一块儿使用时,字段扩展名才有效。若是组合不兼容的指令和扩展,则此方法将引起无效参数异常。

Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));

Response.Cache.SetExpires(DateTime.Parse("6:00:00PM"));

Response类的Cache属性用于获取页面缓存策略。该属性的数据类型是HttpCachePolicy。可经过调用Response.Cache来获取HttpCachePolicy实例,进而实现对于当前页面输出缓存的设置。如上代码所示,第一行代码表示输出缓存时间是60秒,而且页面不随任何GET或POST参数改变,等同于“<%@ OutputCache Duration="60" VaryByParam="none" %>”。第二行代码设置缓存过时的绝对时间是当日下午6时整。

4、页面部分缓存

有时缓存整个页面是不现实的,由于页的某些部分可能在每次请求时都须要变化。在这些状况下,只能缓存页的一部分。顾名思义,页面部分缓存是将页面部份内容保存在内存中以便响应用户请求,而页面其余部份内容则为动态内容。在页面中常常存在某些部分固定不变(如导航栏,页面右侧的排行榜等信息),而其余内容则须要根据用户请求的不一样动态生成。因此咱们能够将固定部分的内容缓存在服务器内存中,以减小服务器查询数据时间。

页面部分缓存也称为控件缓存,这种方式容许将须要缓存的信息包含在一个用户控件内。而后,将该用户控件标记为可缓存的,以此来缓存页面输出的部份内容。这种方式容许缓存页面中的特定内容,而不缓存整个页面。例如,若是要建立一个显示大量动态内容(如股票信息)的页,其中有些部分为静态内容(如每周总结),这时能够将静态部分放在用户控件中,并容许缓存这些内容。

页面部分缓存示例以下: 

CacheControl.ascx的页头代码中添加声明语句:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="CacheControl.ascx.cs" Inherits="CacheControl" %>

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

<%=DateTime.Now %>  

调用该控件的页面代码:

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CacheDemo.aspx.cs"%>
<%@ Register src="CacheControl.ascx" tagname="CacheControl" tagprefix="uc" %>
<head runat="server">
    <title>CacheDemo</title>
</head>
<body>
    <form id="form1" runat="server">
    页面的时间:<%=DateTime.Now %> <br/>
  控件的时间:<uc:CacheControl ID="CacheControl" runat="server" /><br/>
    </form>
</body> 
</html>

当刷新页面时,“页面的时间”每次刷新都变化,而“控件的时间”的数据倒是60秒才变化一次。说明对页面的“局部”控件实现了缓存,而页面其它部分不受影响。

5、 应用程序数据缓存

应用程序数据缓存提供了一种编程方式,可经过键/值对将任意数据存储在内存中。使用应用程序缓存与使用应用程序状态相似。可是,与应用程序状态不一样的是,应用程序数据缓存中的数据是易失的,即数据并非在整个应用程序生命周期中都存储在内存中。应用程序数据缓存的优势是由ASP.NET管理缓存,它会在项过时、无效,或内存不足时移除缓存中的项。还能够配置应用程序缓存,以便在移除项时通知应用程序。

以下所示插入一个字符串进缓存:

Cache["name"]="CacheDemo";

这个存储的字串值能够像这样获得:

if (Cache["name"] != null)
{
string name = Cache["name"].ToString();
}

6、 缓存依赖

前文的几种方式均可以实现数据缓存功能,但问题是数据有时候是在变化的。这样用户可能在缓存期间查询的数据就是过时的数据,从而致使数据的不一致。那有没有办法在数据变化时,系统能自动更新缓存中的数据,从而让用户获得实时有效的数据。

.NET已经为咱们提供了这样一种很是好的解决方法:SqlCacheDependency数据库缓存依赖。下面就让咱们看一下如何实现数据库缓存依赖功能:

1. 配置SqlCacheDependency 

修改web.config,让项目启用SqlCacheDependency。

<?xml version="1.0"?>
<configuration>
    <appSettings/>
    <connectionStrings>
        <add name="strcodematic" connectionString="data source=dbserver;initial catalog=codematic;user id=sa;password=sa"  providerName="System.Data.SqlClient" />
    </connectionStrings>
    <system.web>
        <caching>
            <sqlCacheDependency enabled="true" pollTime="6000">
                <databases>
 <add name="codematic" connectionStringName="strcodematic" />
                </databases>
            </sqlCacheDependency>         
        </caching>
      <compilation debug="true">
        </compilation>     
        <authentication mode="Windows"/>    
    </system.web>
</configuration> 

注意:在<databases>节的<add name="codematic" connectionStringName="strcodematic" />中的name属性值必须和第三步的Page_Load代码中System.Web.Caching.SqlCacheDependency("codematic", "P_Product"); 中的第一个参数(数据库名称)相一致。

这里的connectionStringName指定了在<connectionStrings>中添加的某一个链接字符串。name则是为该SqlCacheDependency起的名字,这个名字将在第三步中用到。

SqlCacheDependency类会自动完成对此配置节信息的读取,以创建和数据库之间的联系。

2.启用缓存依赖

若是要启用SqlCacheDependency,则须要以命令行的方式执行。

aspnet_regsql.exe工具位于Windows\\Microsoft.NET\\Framework\\[版本]文件夹中。

aspnet_regsql -C "data source=.;initial catalog=codematic;user id=sa;password=123456" -ed -et -t "BookInfo"

参数-C后面的字符串是链接字符串(请替换成本身所须要的值),参数-t后面的字符串是数据表的名字。

 运行结果如图所示:

命令执行后,在指定的数据库中会多出一个AspNet_SqlCacheTablesForChangeNotification表。

要使得7.0或者2000版本以上的SQLServer支持SqlCacheDependency特性,须要对数据库服务器执行相关的配置。

有两种方法配置SQLServer:

一 使用aspnet_regsql命令行工具。

二 使用SqlCacheDependencyAdmin类。(msdn看到的,没用过

例如:

aspnet_regsql -S "server" -E -d "database" –ed

或者

aspnet_regsql -S "server" -E -d "database" -et -t "table"

若是是Sql验证的话要把-E换成,-U (用户名),-P (密码)

如下是该工具的命令参数说明:

-? 显示该工具的帮助功能;

-S 后接的参数为数据库服务器的名称或者IP地址;

-U 后接的参数为数据库的登录用户名;

-P 后接的参数为数据库的登录密码;

-E 使用当前登陆用户的 Windows 集成认证进行身份验证;

-d 后接参数为对哪个数据库采用SqlCacheDependency功能;

-C 链接数据库的链接字符串。若是您指定服务器(-S)和登陆(-U和-P,或 -E)信息,则此选项不是必需的,由于链接字符串已经包含这些信息;
-t 后接参数为对哪个表采用SqlCacheDependency功能;
-ed 容许对数据库使用SqlCacheDependency功能;
-dd 禁止对数据库采用SqlCacheDependency功能;
-et 容许对数据表采用SqlCacheDependency功能;
-dt 禁止对数据表采用SqlCacheDependency功能;
-lt 列出当前数据库中有哪些表已经采用sqlcachedependency功能;

3.0使用SqlCacheDependency 

在代码中使用缓存,并为其设置SqlCacheDependency依赖:

 

/// <summary>
/// 获取当前应用程序指定CacheKey的Cache对象值
/// </summary>
/// <param name="CacheKey">索引键值</param>
/// <returns>返回缓存对象</returns>
public static object GetCache(string CacheKey)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    return objCache[CacheKey];
}
/// <summary>
/// 设置以缓存依赖的方式缓存数据
/// </summary>
/// <param name="CacheKey">索引键值</param>
/// <param name="objObject">缓存对象</param>
/// <param name="cacheDepen">依赖对象</param>
public static void SetCache(string CacheKey, object objObject, System.Web.Caching.CacheDependency dep)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    objCache.Insert(
        CacheKey,
        objObject,
        dep,
        System.Web.Caching.Cache.NoAbsoluteExpiration,//从不过时
        System.Web.Caching.Cache.NoSlidingExpiration,//禁用可调过时
        System.Web.Caching.CacheItemPriority.Default,
        null);
}
protected void Page_Load(object sender, EventArgs e)
{
    string CacheKey = "cachetest";
    object objModel = GetCache(CacheKey);//从缓存中获取
    if (objModel == null)//缓存里没有
    {
        objModel = GetData();//把当前时间进行缓存
        if (objModel != null)
        {
            //依赖数据库codematic中的P_Product表变化 来更新缓存
            System.Web.Caching.SqlCacheDependency dep = new System.Web.Caching.SqlCacheDependency("CodeMatic", "P_Product");
            SetCache(CacheKey, objModel, dep);//写入缓存
        }
    } 
    GridView1.DataSource = (DataSet)objModel;
    GridView1.DataBind();
}

从以上代码能够看出,和文件依赖基本相同,只是在存放缓存SetCache时存入的依赖对象不一样。这里用的是SqlCacheDependency。

其中,建立SqlCacheDependency的构造方法:

public SqlCacheDependency (string databaseEntryName,string tableName)
//databaseEntryName:是在Web.config文件的caching节的sqlCacheDependency的databases元素中定义的数据库的名称。 
//tableName:与SqlCacheDependency关联的数据库表的名称。
//这样,只有当P_Product表的内容发生变化时,查询操做才会从新查询数据更新缓存的内容,能够大大减小数据库的重复查询和提升系统的性能和运行效率。

7、缓存管理类

首先,缓存管理类外部代码定义了各类过时时间的常量,主要用于方便设定缓存的过时时间

/// <summary>
    /// 全站缓存类
    /// </summary>
    public sealed class SiteCache
    {
        // 一天
        public const int DayFactor = 17280;
        // 一小时
        public const int HourFactor = 720;
        // 一分钟
        public const int MinuteFactor = 12; 
        // 一秒
        public const double SecondFactor = 0.2;

        private static int factor = 5;
        /// <summary>
        /// 时间因子
        /// </summary>
        public static int Factor
        {
            get { return factor; }
            set { factor = value; }
        }

 public static Cache CurrentCache {
            get {
                return HttpRuntime.Cache;
            }
        }
        }
//Clear方法用于移除全部存储在内存当中的缓存,代码中cacheEnum变量经过GetEnumerator方法得到全部缓存列表,再根据缓存列表来移除缓存。
        public static void Clear()
        {
            //获取缓存中的键设置及其值的字典枚举数
            IDictionaryEnumerator cacheEnum = siteCache.GetEnumerator();
            ArrayList al = new ArrayList();
            //循环添加到数组列表
            while (cacheEnum.MoveNext())
            {
                al.Add(cacheEnum.Key);
            }
            //循环从缓存中移除
            foreach (string key in al)
            {
                siteCache.Remove(key);
            }
        }
//RemoveByPattern方法是经过正则移除对应的缓存。
 public static void RemoveByPattern(string pattern)
        {
            IDictionaryEnumerator cacheEnum = siteCache.GetEnumerator();
            Regex regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
            ArrayList al = new ArrayList();
            //循环从缓存中取出键进行正则条件匹配
            while (cacheEnum.MoveNext())
            {
                //匹配正确则添加到数组列表
                if (regex.IsMatch(cacheEnum.Key.ToString()))
                {
                    al.Add(cacheEnum.Key);
                }
            }
            //移除匹配正则的缓存
            foreach (string key in al)
            {
                siteCache.Remove(key);
            }
        }
//Insert方法是经过Cache的插入方法而实现的,主要可以把缓存键、缓存对象、缓存依赖、缓存过时时间、缓存级别这些缓存项插入到内存中。
    /// <summary>
        /// 插入缓存项
        /// </summary>
        public static void Insert(string key, object value, System.Web.Caching.CacheDependency dep, int seconds, CacheItemPriority priority)
        {
            if (value != null)
            {
                siteCache.Insert(key, value, dep, DateTime.Now.AddSeconds(Factor * seconds), TimeSpan.Zero, priority, null);
            }
        }
//Get方法经过指定的键从Cache中获取缓存
        public static object Get(string key)
        {
            return siteCache[key];
        }
    }

 8、缓存的应用规则

缓存分配的有效期不要过短。
缓存那些常常被访问,同时变化频率不大的数据。
缓存整个应用程序都要使用的设置或对象,而且这些设置和对象在生存期内不会频繁变化。
不要缓存太多项,缓存每一个项均有开销。
不要缓存不多使用的项。
不要缓存容易从新计算或随时均可能会修改的对象,如购物车。
不要缓存敏感信息,不然其余人很容易取得这些信息。

好比:能够缓存网站信息配置

GetConfig是一个泛型方法,网站信息配置里的全部功能属性都是经过它来得到对象。方法后面跟着一个where子句,用于指定对类型的约束。其中class限制了类型参数必须是引用类型, new()限制了该类型参数必须具备无参数的公共构造函数。

方法内首先获取了T变量的类型。而后根据类型名拼装成configCacheKey缓存键,经过SiteCache类的Get方法获取缓存的值并存储到configObject变量中。接着判断该缓存是否不存在值,若是不存在,使用GetConfigPath方法得到了T变量的物理文件地址。

public static T GetConfig<T>() where T : class, new()
{
     Type configClassType = typeof(T);
     string configCacheKey = "CK_SiteConfigCode_" + configClassType.Name;
     object configObject = SiteCache.Get(configCacheKey);
     if (configObject == null)
     {
          string configFilePath = GetConfigPath<T>();
//下面检查T变量的物理文件地址是否存在,若是存在即读取T变量的配置信息,并将信息插入到缓存中。其中Insert方法使用了缓存依赖CacheDependency实例监视文件或目录路径,当该资源更改时,缓存的对象将过期,从缓存中移除。
          if (File.Exists(configFilePath))
          {
              using (XmlTextReader xmlTextReader = new XmlTextReader(configFilePath))
              {
                   XmlSerializer xmlSerializer = new XmlSerializer(configClassType);
                   configObject = xmlSerializer.Deserialize(xmlTextReader);
              }
              SiteCache.Insert(configCacheKey, configObject, new CacheDependency(configFilePath)); 
          }
     }
//最后,把缓存对象转换为T泛型变量。判断是否为空,若是是则建立新的T实例返回,不然将原有值返回。
     T config = configObject as T;
     if (config == null)
     {
         return new T();
     }
     else
     {
         return config;
     }
}
 
相关文章
相关标签/搜索