1.页面缓存
顶部加上
//参数: duration->缓存的时间以秒为单位,必须
localhost->指定应该输出缓存的位置,参数列表是:any,client,downstream,none,server,serverandclient,可选
varybyparam->request中变量的名称,这些变量应该产生单独的缓存条目,"none"表示没有变动,"*"为每个不同的数量数组创建新的缓存条目,变量之间用";"分开,必须
varybyheader->基于指定的标头中的变动改变缓存条目,可选
varybycustom->允许在global.aspx中指定自定义变动,(如:"broser"),可选
<%@ outputcache duration="60" varybyparam="*" %>
//是每个浏览器都具有单独的缓存条目,设置varbycustom的值为"browser"
<%@ outputcache duration="60" varbyparam="none" varbycustom="browser" %>
//片段缓存用户控件缓存
片段缓存语法与页面级输出缓存一样,但其应用于用户控件(.ascx文件)而不是web窗体(.aspx文件),除了location属性,其他属性都支持
片段缓存还支持名为varybycontrol的outputcache属性,该属性将用户控件(通常指页面上的控件,如dropadownlist)的成员值改变控件的缓存
指定了varbycontrol可以省略varbyparam,默认情况下对页面的每个用户控件都单独进行缓存,
如果用户控件不随页面改变,并且在所有页面都使用相同的名称,则可以使用shared="true"参数,该参数将使用用户控件的缓存版本供所有引用该控件
的页面使用
示例:
<%@ outputcache duration="60" varbyparam="*" %>
该示例将缓存用户控件60秒,并且将针对查询字符串的每个变动,针对此控件所有的每个页面创建单独的缓存条目
<%@ outputcache duration="60" varbyparam="none" varbycontrol="categorydropdownlist" %>
该示例将缓存用户控件60秒,并且将针对categorydropdownlist控件的每个不同的值,针对此控件所在的每个页面创建单独的缓存条目
<%@ outputcache duration="60" varbyparam="none" varbycustom="browser" shared="true" %>
该示例将缓存用户控件60秒,并且针对每个浏览器名称和主要版本创建一个缓存条目,然后每个浏览器的缓存条目将由此引用此用户控件的所有页面共享(只要所有页面都使用相同的id引用该控件即可)
在cache中缓存数据
cache["key"]="value";
这种做法将缓存中存储项,同时不带任何依赖项,因此它不会到期,除非缓存引擎为了给其他缓存数据提供空间而将其删除,要包括特定的缓存依赖项,可以使用add()或insert()方法,add()和insert()之间的唯一区别是,add()返回对已缓存对象的引用,而insert()没有返回值
cache,insert("key",myxmlfileddata,new System.Web.caching.cachedependency(server.mappath("users.xml")));
该示例可以将文件中的xml数据插入缓存,无需在以后请求时从文件读取,cachedependency的作用是确保缓存在文件夹更改后立即到期,以便可以从文件中提取最新数据,重新进行缓存,如果缓存的数据来自若干个文件,还可以指定一个文件名数组
cache.insert("dependentkey",mydependentdata,new System.Web.caching.cachedependency(new string[]{},new string[]{"key"}));
该示例可插入键值为"key"的第二个数据块(取决于是否存在第一个数据块),如果缓存中不存在名为"key"的键,或者如果与该键相关联的项3已到期或被更新,则"dependentkey"的缓存条目将到期
cache.insert("key",mytimesensitivedata,null,datetime.now.addminutes(1),timespan.zero);
绝对到期:此示例将对受时间影响的数据缓存一分钟,一分钟过后,缓存将到期
注意,绝对缓存和滑动到期不能一起使用
cache.insert("key",myfrequentiyaccesseddata,null,System.Web.caching.cache.noabsoluteexpiration,timespan.fromminutes(1));
滑动到期:此示例将缓存一些频繁使用的数据,数据将在缓存中一直保留下去,除非数据未被引用的时间达到一分钟
注意,滑动到期和绝对到期不能一起使用
除了上面提到的依赖项,我们还可以指定项的优先级(依次为low,high,notremovable,它们是在System.Web.caching.cacheitempriority枚举中定义的)以及当缓存中的项到期时调用的cacheitemremovedcallback函数,大多数时候,默认的优先级已经足够一级缓存引擎可以正常完成任务并处理缓存的内存管理
cacheitemremovedcallback选项考虑到一些有趣的可能性,但实际上很少使用
cacheitemremovedcallback示例:
System.Web.caching.cacheitemremovedcallback callback=new System.Web.caching.cacheitemremovedcallback(onremove);
cache.insert("key",myfile,null,System.Web.caching.cache.noabsoluteexpiration,timespan.zero,System.Web.caching.cacheitempriority.default,callback);
...
public static void onremove(string key,Object cacheitem,System.Web.caching.cacheitemremovedreason reason){
//记录任何逻辑来记录缓存中的数据到期的原因
appendlog("the cached value with key"+key+"was removed from then cache reason "+reason.ToString());
}
通过从缓存中删除项时记录这些项并记录删除的原因,你可以确定是否在有效地使用缓存或者您是否可能需要增加服务器上的内存
注意,callback是一个静态类方法,建议使用该方法的原因是,如果不使用它,保存回调函数的类的实例将保留在内存中,以支持回调
缓存数据引用模式
public datatable getcustomers(bool bypasscache){
string cachekey="customersdatatable";
Object cacheitem=cache[cachekey] as datatable;
if((bypasscache)(cacheitem==null)){
cacheitem=getcustomersfromdatasource();
cache.insert(cachekey,cacheitem,null,datetime.now.addseconds(getcachesecondsfromconfig(cachekey)),timespan.zero);
}
return (datatable)cacheitem;
}
关于此模式,有以下几点需要注意:
某些值(例如,cachekey、cacheitem 和缓存持续时间)是一次定义的,并且只定义一次。
可以根据需要跳过缓存 — 例如,当注册一个新客户并重定向到客户列表后,最好的做法可能就是跳过缓存,用最新数据重新填充缓存,该数据包括新插入的客户。
缓存只能访问一次。这种做法可以提高性能,并确保不会发生 nullreferenceexceptions,因为该项在第一次被检查时是存在的,但第二次检查之前就已经到期了。
该模式使用强类型检查。c# 中的 "as" 运算符尝试将对象转换为类型,如果失败或该对象为空,则只返回 null(空)。
持续时间存储在配置文件中。在理想的情况下,所有的缓存依赖项(无论是基于文件的,或是基于时间的,还是其他类型的依赖项)都应该存储在配置文件中,这样就可以进行更改并轻松地测量性能。我还建议您指定默认缓存持续时间,而且,如果没有为所使用的 cachekey 指定持续时间,就让 getcachesecondsfromconfig() 方法使用该默认持续时间。
相关的代码示例是一个 helper 类,它将处理上述所有情况,但允许通过一行或两行代码访问缓存的数据。请下载 cachedemos.msi。
小结
缓存可以使应用程序的性能得到很大的提高,因此在设计应用程序以及对应用程序进行性能测试时应该予以考虑。应用程序总会或多或少地受益于缓存,当然有些应用程序比其他应用程序更适合使用缓存。对 asp.net 提供的缓存选项的深刻理解是任何 asp.net 开发人员应该掌握的重要技巧。
尽早缓存;经常缓存
缓存可以掩盖许多过失
页面级输出缓存