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清空缓存时遇到问题详细分析,为了让大家更好地解决此类问题,希望本文对大家的学习有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索asp.net清空缓存
asp.net缓存清除
,以便于您获取更多的相关知识。

时间: 2025-01-07 18:46:52

ASP.NET清空缓存时遇到的问题简析_实用技巧的相关文章

ASP.NE网站发布注意事项简析_实用技巧

ASP.NET网站部署到IIS中的关键点: 1.Windows XP运行IIS的帐号为"计算机名\ASPNET",Windows Vista.Windows Server 2003运行 IIS的帐号为"NETWORK SERVICE".如果网站下的某个文件夹供用户上传图片.文件, 则运行IIS的帐号必须拥有对该文件夹的完全控制权限.对于Windows XP,首先要在 Windows资源管理器中的"工具"菜单中选择"文件夹选项"

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

相关文章:ASP.NET 缓存全解析 在网站中要做一个清理缓存的功能(也就是在缓存为到期之前就强制缓存过期),程序中有的地方使用的HttpRuntime.Cache来做的缓存,而和数据库交互部分则使用ObjectDataSource提供的缓存机制.清理HttpRuntime.Cache的缓存很简单,只要下面的代码就可以了. List<string> keys = new List<string>(); // retrieve application Cache enumerator

一起谈.NET技术,浅析ASP.NET清空缓存时遇到的问题

相关文章:ASP.NET 缓存全解析 在网站中要做一个清理缓存的功能(也就是在缓存为到期之前就强制缓存过期),程序中有的地方使用的HttpRuntime.Cache来做的缓存,而和数据库交互部分则使用ObjectDataSource提供的缓存机制.清理HttpRuntime.Cache的缓存很简单,只要下面的代码就可以了. List<string> keys = new List<string>();// retrieve application Cache enumeratorI

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

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

GridView中日期不显示时分秒的完美解决方法_实用技巧

两种处理方式: 1.模版列:假设数据表的字段completeTime的类型为时间格式 <asp:TemplateField HeaderText="时间"> <ItemTemplate> <%#Eval("completeTime", "{0:yyyy-MM-dd}")%> </ItemTemplate> </asp:TemplateField> 2.绑定列: <asp:Bound

ASP.NET 缓存分析和实践浅析提高运行效率_实用技巧

向数据层.业务逻辑层.UI 或输出层添加缓存支持.内存现在非常便宜 - 因此,通过以智能的方式在整个应用程序中实现缓存,可以获得很大的性能提高. 缓存可以掩盖许多过失 缓存是一种无需大量时间和分析就可以获得"足够良好的"性能的方法. 这里再次强调,内存现在非常便宜,因此,如果您能通过将输出缓存 30 秒,而不是花上一整天甚至一周的时间尝试优化代码或数据库就可以获得所需的性能,您肯定会选择缓存解决方案(假设可以接受 30 秒的旧数据).缓存正是那些利用 20% 付出获得 80% 回报的特

充分利用ASP.NET的三种缓存提高站点性能的注意方法_实用技巧

ASP.NET提供三种主要形式的缓存:页面级输出缓存.用户控件级输出缓存(或称为片段缓存)和缓存API. 尽早缓存:经常缓存  您应该在应用程序的每一层都实现缓存.向数据层.业务逻辑层.UI或输出层添加缓存支持.内存现在非常便宜-因此,通过以智能的方式在整个应用程序中实现缓存,可以获得很大的性能提高. 页面级输出缓存 最简单的缓存形式,只是在内存中保留为响应请求而发送的HTML的副本. 要实现页面输出缓存,只要将一条OutputCache指令添加到页面即可. <%@ OutputCache Du

asp.net服务器端指令include的使用及优势介绍_实用技巧

      asp.net中的服务端包括指令简单点就是一个<!-- #include file|virtual="filename" –>这样的指令,msdn中的名词解释是:将指定文件的内容插入 ASP.NET 文件中,包括网页(.aspx 文件).用户控件文件(.ascx 文件)和 Global.asax 文件.插入静态文件这个基本功能就不说了,插入aspx.ascx,这功能算是挺强了,asax哥就有点困惑了,这个暂且不管,今天要说的就是这个指令. 尴尬的存在     服

ASP.NET MVC小结之基础篇(二)_实用技巧

整理除了这个笔记,共享一下子,基本MVC的所有东西都介绍了,但是都是很基础的东西.本来打算一篇发表完的,但是发现东西有点多,所以分成了两篇文章,这是最后一篇了! 1.ASP.NET MVC请求过程 1 2.Controller (1) 控制器在ASP.NET MVC中扮演着处理客户端请求的角色 1)必须实现System.Web.Mvc.IController接口 ->通常直接继承System.Web.MVC.Controller类 2)必须要以Controller结尾 3)通过不同的Action