ASP.NET清空缓存时遇到的问题简析

在网站中要做一个清理缓存的功能(也就是在缓存为到期之前就强制缓存过期),程序中有的地方使用的HttpRuntime.Cache来做的缓存,而和数据库交互部分则使用ObjectDataSource提供的缓存机制。清理HttpRuntime.Cache的缓存很简单,只要

List<string> keys = new List<string>();
   // retrieve application Cache enumerator
IDictionaryEnumerator enumerator = HttpRuntime.Cache.GetEnumerator();
   // copy all keys that currently exist in Cache
   while (enumerator.MoveNext())
   {
    keys.Add(enumerator.Key.ToString());
   }
   // delete every key from cache
   for (int i = 0; i < keys.Count; i++)
   {
    HttpRuntime.Cache.Remove(keys[i]);
   } 

就可以了。

本以为ObjectDataSource等数据源的缓存也是保存在HttpRuntime.Cache中,经过测试没想到竟然不是,因为执行上面的代码以后ObjectDataSource仍然是从缓存读取数据。

使用Reflector反编译发现ObjectDataSource是使用HttpRuntime.CacheInternal来实现的缓存。CacheInternal是internal的,因此没法直接写代码调用,同时CacheInternal中也没提供清空缓存的方法,只能通过实验发现_caches._entries是保存缓存的Hashtable,因此就用反射的方法调用CacheInternal,然后拿到_caches._entries,最后clear才算ok。

最终代码如下:

//HttpRuntime下的CacheInternal属性(Internal的,内存中是CacheMulti类型)是
ObjectDataSource等DataSource保存缓存的管理器
//因为CacheInternal、_caches、_entries等都是internal或者private的,
所以只能通过反射调用,而且可能会随着.Net升级而失效
 object cacheIntern = CommonHelper.GetPropertyValue(typeof(HttpRuntime), "CacheInternal") as IEnumerable;
 //_caches是CacheMulti中保存多CacheSingle的一个IEnumerable字段。
 IEnumerable _caches = CommonHelper.GetFieldValue(cacheIntern, "_caches") as IEnumerable;
 foreach (object cacheSingle in _caches)
 {
  ClearCacheInternal(cacheSingle);
 } 

private static void ClearCacheInternal(object cacheSingle)
{
 //_entries是cacheSingle中保存缓存数据的一个private Hashtable
 Hashtable _entries = CommonHelper.GetFieldValue(cacheSingle, "_entries") as Hashtable;
 _entries.Clear();
} 

mary>
/// 得到type类型的静态属性propertyName的值
/// </summary>
/// <param name="type"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
public static object GetPropertyValue(Type type, string propertyName)
{
 foreach (PropertyInfo rInfo in type.GetProperties
(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance))
 {
  if (rInfo.Name == propertyName)
  {
   return rInfo.GetValue(null, new object[0]);
  }
 }
 throw new Exception("无法找到属性:" + propertyName);
} 

/// <summary>
/// 得到object对象的propertyName属性的值
/// </summary>
/// <param name="obj"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
public static object GetPropertyValue(object obj, string propertyName)
{
 Type type = obj.GetType();
 foreach (PropertyInfo rInfo in type.GetProperties
(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance))
 {
  if (rInfo.Name == propertyName)
  {
   return rInfo.GetValue(obj, new object[0]);
  }
 }
 throw new Exception("无法找到属性:" + propertyName);
} 

public static object GetFieldValue(object obj, string fieldName)
{
 Type type = obj.GetType();
 foreach (FieldInfo rInfo in type.GetFields
(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance))
 {
  if (rInfo.Name == fieldName)
  {
   return rInfo.GetValue(obj);
  }
 }
 throw new Exception("无法找到字段:" + fieldName);
}

上面方法由于是通过crack的方法进行调用,可能有潜在的问题,因此仅供参考。

在google上搜索到另外一篇文章,主干是代码,代码的思路和我一样,贴过来也供参考。

private void clearOutputCache()
{
 Type ct = this.Cache.GetType();
 FieldInfo cif = ct.GetField( "_cacheInternal", BindingFlags.NonPublic | BindingFlags.Instance );
 Type cmt = Cache.GetType().Assembly.GetType( "System.Web.Caching.CacheMultiple" );
 Type cachekeyType = Cache.GetType().Assembly.GetType( "System.Web.Caching.CacheKey" );
 FieldInfo cachesfield = cmt.GetField( "_caches", BindingFlags.NonPublic | BindingFlags.Instance ); 

 object cacheInternal = cif.GetValue( this.Cache );
 object caches = cachesfield.GetValue( cacheInternal ); 

 Type arrayType = typeof( Array );
 MethodInfo arrayGetter = arrayType.GetMethod( "GetValue", new Type[] { typeof( int ) } );
 object cacheSingle = arrayGetter.Invoke( caches, new object[] { 1 } ); 

 FieldInfo entriesField = cacheSingle.GetType().GetField( "_entries", BindingFlags.Instance | BindingFlags.NonPublic );
 Hashtable entries = (Hashtable) entriesField.GetValue( cacheSingle ); 

 List<object> keys = new List<object>();
 foreach( object o in entries.Keys )
 {
  keys.Add( o );
 } 

 MethodInfo remove = cacheInternal.GetType().GetMethod( "Remove", BindingFlags.NonPublic | BindingFlags.Instance, null,
  new Type[] { cachekeyType, typeof( CacheItemRemovedReason ) }, null );
 foreach( object key in keys )
 {
  remove.Invoke( cacheInternal, new object[] { key, CacheItemRemovedReason.Removed } );
 }
}

以上就是对ASP.NET清空缓存时遇到问题详细分析,为了让大家更好地解决此类问题,希望本文对大家的学习有所帮助。

(0)

相关推荐

  • ASP.NET 清除模式窗口数据缓存的操作方式

    使用模式窗口showModalDialog()弹出页面在asp.net中经常用到 用的最多的就是点击"修改"按钮,弹出修改页面:修改成功之后,关闭修改页面,刷新父页面. 目前存在的一个问题是,刷新完父页面之后,再点击修改按钮弹出修改页面,修改页面显示的数据却不是修改后的数据,还是第一次弹出修改页面的旧数据,这里就涉及到了清除模式窗口缓存数据的问题. 这涉及到ShowModalDialog缓存机制的问题,需要我们手动添加一些代码来清除缓存. 操作方式如下: 首先在前台界面(即aspx的界

  • ASP.NET网站管理系统退出 清除浏览器缓存,Session的代码

    1.在系统登陆成功时记录登陆的用户名.密码等信息(登陆功能的部分代码) 复制代码 代码如下: Session["id"] = user.id.ToString(); Session["name"] = user.name.ToString(); Session["pwd"] = user.password.ToString(); Session["time"] = user.LoginTime.ToString(); Sess

  • ASP.NET缓存管理的几种方法

    尽管缓存管理在Windows应用程序中已经不再是个问题,但在web环境下依然是个挑战.因为HTTP是一个无状态的协议并且web服务无法识别不同请求的用户.识别不同的请求究竟是哪个特定用户发出的,并且存储这些信息以便它在以后请求中能被重新使用,对我们来说非常重要.ASP.NET提供了很多特性用来在客户端和服务器端存储这些数据,但是有时我们会对"我们什么时候使用它们(哪个)"感到疑惑.在ASP.NET中,我们会遇到像Session,Application以及Cache这些对象,为了有效地在

  • asp.net中Session缓存与Cache缓存的区别分析

    其中Cookie是保存在客户端的一组数据,主要用来保存用户名等个人信息. Session则保存对话信息. Application则是保存在整个应用程序范围内的信息,相当于全局变量. Session用的比较多. Session缓存与Cache缓存的区别,可以参考如下的几点: 1.最大的区别是Cache提供缓存依赖来更新数据,而Session只能依靠定义的缓存时间来判断缓存数据是否有效. 2.即使应用程序终止,只要Cache.Add方法中定义的缓存时间未过期,下次开启应用程序时,缓存的数据依然存在.

  • ASP.NET 4中的可扩展输出缓存(可以缓存页面/控件等)

    输出缓存的前世今生 ASP.NET 1.0引入输出缓存的概念,这使得开发者可以缓存页面.控件.控制器以及HTTP响应的输出到内存中.在后续的Web请求,ASP.NET就可以使用缓存中的内容更快响应. ASP.NET的输出缓存系统足够灵活,使得我们可以根据不同的查询字符串或者表单post参数来缓存不同版本的内容.例如test.aspx?category=Vegerable 和 test.aspx?category.aspx?category=Meat.它也允许我们根据浏览器类型或者用户语言偏好来缓

  • asp.net(C#)遍历memcached缓存对象

    STATS命令 遍历memcached缓存对象(C#)转载之青草堂 出于性能考虑,memcached没有提供遍历功能,不过我们可以通过以下两个stats命令得到所有的缓存对象. 1.stats items 显示各个slab中item的数目. 2.stats cachedump slab_id limit_num 显示某个slab中的前limit_num个key列表,显示格式:ITEM key_name [ value_length b; expire_time|access_time s] 除了

  • asp.net 提高网站速度及如何利用缓存

    输出缓存和片段缓存的优点是非常易于实现,在大多数情况下,使用这两种缓存就足够了.而缓存API则提供了额外的灵活性(实际上是相当大的灵活性),可用于在应用程序的每一层利用缓存.本文全面介绍了这三种缓存技术在系统各层中的应用. 在ASP.NET提供的许多特性中,缓存支持无疑是我最欣赏的特性,我这样说当然是有充分理由的.相比ASP.NET的所有其他特性,缓存对应用程序的性能具有最大的潜在影响,利用缓存和其他机制,ASP.NET开发人员可以接受使用开销很大的控件(例如,DataGrid)构建站点时的额外

  • ASP.NET页面在IE缓存的清除办法

    以前没有注意到这个问题,今天在看Blog的时候发现有篇文章不错,或许以后值得借鉴: 一般情况下,WEB页面都会在Internet临时文件夹中有一个临时文件.我在操作IE时会出现这种情况:假如说有一个页面Page1.aspx,在我第一次访问后,它会在我的Internet临时文件夹里有一个Page1.aspx文件生成.之后,如果我改了Page1.aspx的数据后再次访问该页面,发现IE并没有对这个Page1.aspx的数据进行更新,反而打开的是我第一次访问的页面.为什么会这样,是因为IE自动(默认)

  • asp.net 客户端浏览器缓存的Http头介绍

    让浏览器做缓存需要给浏览器发送指定的Http头,告诉浏览器缓存多长时间,或者坚决不要缓存.作为.net的程序员,其实我们一直都在用这种方法,在OutputCache指令中指定缓存的Location为Client时,其实就是给浏览器发送了一个Http头,告诉浏览器这个Url要缓存多长时间,最后修改的时间. 微软在OutputCacheModule中对这些缓存用到的Http头给我们进行了很好的封装,但是了解这些Http头可以更灵活的使用它们. 和客户端缓存相关的Http头有以下几个,分别是: 1.

  • Asp.net禁用页面缓存的方法总结

    1.在Asp页面首部<head>加入  复制代码 代码如下: Response.Buffer   =   True      Response.ExpiresAbsolute   =   Now()   -   1      Response.Expires   =   0      Response.CacheControl   =   "no-cache"      Response.AddHeader   "Pragma",   "No-

  • ASP.NET缓存介绍

    ASP.NET缓存 介绍 缓存是在内存存储数据的一项技术,也是ASP.NET中提供的重要特性之一.例如你可以在复杂查询的时候缓存数据,这样后来的请求就不需要从数据库中取数据,而是直接从缓存中获取.通过使用缓存可以提高应用程序的性能. 主要有两种类型的缓存: 输出缓存Output caching\ 数据缓存Data caching 1. 输出缓存(Output Caching) 使用输出缓存,你可以缓存最后输出的HTML页面,当相同的页面再次请求的时候,ASP.NET不会再执行页面的生命周期和相关

  • 设置ASP.NET页面不被缓存(客户端/服务器端取消缓存方法)

    复制代码 代码如下: /// <summary> /// 设置页面不被缓存 /// </summary> private void SetPageNoCache() { Response.Buffer = true; Response.ExpiresAbsolute = System.DateTime.Now.AddSeconds(-1); Response.Expires = 0; Response.CacheControl = "no-cache"; Res

  • ASP.net Substitution 页面缓存而部分不缓存的实现方法

    文件1:Deafault.aspx 复制代码 代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <%@ outputcache duration="10" varybyparam="none" %> <!-

  • ASP.NET性能优化之让浏览器缓存动态网页的方法

    OutputCache是针对所有访问服务器资源的用户,本篇要介绍的浏览器缓存则是针对单个用户,让浏览器在我们的控制下彻底不持续访问服务器上的动态内容,也就是我们要让浏览器变成我们的缓存机制中的一部分,在某些特定的场景下最大化地提升ASP.NET站点的性能.如果说OutputCache是从广度上提升并发效率,则浏览器缓存是从深度上提升效率. 一:HTTP头简介 1.1浏览器第一次请求 假设我们请求一个URL地址,譬如我服务器上的一个静态页面http://192.168.0.77/luminji2/

  • 解决asp.net Sharepoint无法连接发布自定义字符串处理程序,不能进行输出缓存处理的方法

    问题描述: 无法连接发布自定义字符串处理程序,不能进行输出缓存处理.IIS 实例 ID 为"1772638466", URL 为"http://XXXX.XXX.XXX/EnglishWorld/Default.aspx". 有关更多信息,请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心. 在系统日志大片出现(除了URL不同),但貌似对系统没什么影响,能正常使用. 此问题不会影响正常使用,但日志很快就满了

  • asp.net 使用驻留在页面中的Cache缓存常用可定时更新的数据

    就是希望让Web应用程序从一开始运行到结束都一直存在,有人就说为什么不用Application呢?其实Cache是可以一段时间内自动更新数据的,而Application就无法做成这样的,另外Application在Web这种高并发的系统中一定要考虑线程安全的问题,Application本身就不是线程安全的,而Cache就是线程安全.所以一般我都会在很多对象中我只从Web开始运行的时候从数据库或文件里获取一次数据,在不同的页面中,都是使用Cache的,而且Cache中的数据可能弄成自动更新的,所以

随机推荐