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

  相关文章: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来实现的缓存,气氛呀,为什么微软总爱搞“特殊化”,对外提供一个Cache用,自己偷偷用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;

for
each (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();

}

/// <summary>

/// 得到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上搜索到另外一篇文章 http://www.msdnkk.hu/Articles/Clear_OutputCache-Minden_oldal_torlese ,由于是匈牙利文的,也看不懂在说什么,不过主干是代码,看他代码的思路和我一样,贴过来也供参考:

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 } );

}

}

时间: 2024-09-20 05:41:19

浅析ASP.NET清空缓存时遇到的问题的相关文章

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

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

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

在网站中要做一个清理缓存的功能(也就是在缓存为到期之前就强制缓存过期),程序中有的地方使用的HttpRuntime.Cache来做的缓存,而和数据库交互部分则使用ObjectDataSource提供的缓存机制.清理HttpRuntime.Cache的缓存很简单,只要 List<string> keys = new List<string>(); // retrieve application Cache enumerator IDictionaryEnumerator enumer

艾伟_转载:浅析ASP.NET页面缓存的几点体会

前几天遇到个问题,百思不得其解.后来查阅了一些资料心里才有了点思路.把自己遇到的问题记录下来希望能给其他的园友一些帮助吧. 事情是这样的.我的一个ASP.NET页面用window.open导航后再次访问时没有得到更新,确切的说是再次访问时根本就没有访问服务器.可是这个现象在我的机器上并没有出现,而项目组中其他的机器都有此问题.当时我这个郁闷呐,因为不方便调试,最后就在页面上输出好多alert.终于在几次试验之后发现了问题的所在. 其主要问题就是IE缓存了页面,当服务器端出现更新时IE并没有检查到

浅析ASP.NET页面缓存的几点体会

前几天遇到个问题,百思不得其解.后来查阅了一些资料心里才有了点思路.把自己遇到的问题记录下来希望能给其他的园友一些帮助吧. 事情是这样的.我的一个ASP.NET页面用window.open导航后再次访问时没有得到更新,确切的说是再次访问时根本就没有访问服务器.可是这个现象在我的机器上并没有出现,而项目组中其他的机器都有此问题.当时我这个郁闷呐,因为不方便调试,最后就在页面上输出好多alert.终于在几次试验之后发现了问题的所在. 其主要问题就是IE缓存了页面,当服务器端出现更新时IE并没有检查到

Asp.net清空cache禁用页面缓存的方法

 方法1.在Asp页面首部<head>中添加如下代码        Response.Buffer   =   True      Response.ExpiresAbsolute   =   Now()   -   1      Response.Expires   =   0      Response.CacheControl   =   "no-cache"      Response.AddHeader   "Pragma",   "

浅析ASP.NET FORUMS中缓存机制的应用

asp.net|缓存 浅析ASP.NET FORUMS中缓存机制的应用 在ASP.NET中有三种缓存机制,我在这里主要提到的是ASP.NET FORUMS中使用的缓存API Cache对象Cache对象可以说在ASP.NET FORUMS中无所不在,以SiteUrls()类为例在构造函数中有如下代码if (HttpRuntime.Cache[cacheKey] == null) { . .System.Web.Caching.CacheDependency dep = new System.We

ASP.NET HTTP运行时组成详解

asp.net|详解 简介 不管使用哪种底层平台可靠性和性能都是对所有 Web 应用程序的主要要求尽管从某种意义上讲这两个要求是相互矛盾的.例如要构建更可靠.更健壮的应用程序可能需要将 Web 服务器与具体的应用程序分离使应用程序在进程外工作.但是如果在不同于 Web 服务器进程的内存环境中工作应用程序将变慢.因此需要采取合理的措施以确保进程外代码尽可能快地运行. 在构建 Microsoft? ASP.NET 运行时环境时依据的设计原则即充分考虑可靠性和性能.得到的 ASP.NET 进程模型包含

为ASP.NET应用缓存Oracle数据

asp.net|oracle|缓存|数据 为了创建可扩展.高性能的基于WEB的应用,ASP.NET提供一个称为数据缓存(Data Caching)的特性.数据缓存支持将频繁访问的数据对象可编程地存放在内存中.这一特性可扩展以广泛地提高查询Oracle数据库中数据的ASP.NET应用的性能.本文讲述一个策略,可用于采用Web Farm环境中的ASP.NET Web应用缓存Oracle数据库数据.这个技巧允许在内存中缓存频繁访问的Oracle数据库数据,而不是频繁访问数据库来取数据.这可以帮助避免到

ASP.NET 数据库缓存依赖

asp.net|缓存|数据|数据库 ASP.NET 数据库缓存依赖 By Peter A. Bromberg, Ph.D. 在ASP.NET中,Cache类最酷的特点是它能根据各种依赖来良好的控制自己的行为.以文件为基础的依赖是最有用的,文件依赖项是通过使用 Cache.Insert 并提供引用文件的 CacheDependency 对象添加的 Cache.Insert("MyData", Source, new CacheDependency(Server.MapPath("