一起谈.NET技术,浅析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;
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();
}

/// <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-07-29 16:16:08

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

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

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

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

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

一起谈.NET技术,ASP.NET 4的Demo实践:URL路由改进支持

从.NET框架3.5 SP1开始,微软推出了ASP.NET路由支持,从而实现了特定资源的URL与其对应的Web服务器上的物理文件之间的彻底解耦.借助于ASP.NET路由支持,开发人员可以定义一组路由规则,从而实现把路由模式映射到一个生成相应内容的类.例如,你可以把URLCategories/CategoryName映射到一个类,该类接收CategoryName而最终生成对应于此种类的产品信息显示于一个网格中的一组HTML标记.有了这样的映射,用户便可以通过访问www.yoursite.com/C

一起谈.NET技术,Asp优化,asp缓存技术

一.何谓asp缓存/为什么要缓存 当你的web站点采用asp技术建立的初期,可能感觉到的是asp动态网页技术带来的便利性,以及随意修改性. 自如的http控制.但是,随着访问量的增加,你一定会发现自己的站点访问速度越来越慢,IIS重新启动得越来越频繁.接下来,你一定想优化asp,诸如更换性能更优异的数据库.建立索引.编写存储过程等等.这些措施有些不需要增加成本压力,有些则成本压力很大(譬如丛access到SQL),而且效果还不一定. 面对web访问压力,我认为最经济的办法是利用缓存优化技术来实现

一起谈.NET技术,ASP.NET MVC 2示例Tailspin Travel UI层分析

Tailspin Travel 是一个旅游预订的应用程序示例,最新版本采用ASP.NET MVC 2技术构建,主要使用 DataAnnotations 验证, 客户端验证和ViewModels,还展示了许多Visual Studio 2010, .NET Framework 4, 和Windows Server AppFabric的技术,参看ASP.NET MVC 2示例Tailspin Travel. Tailspin Travel设计的技术比较多,今天我们来看看界面(UI)上的技术,在UI层

一起谈.NET技术,ASP.NET缓存初探 使用得当是关键

缓存是在内存存储数据的一项技术,也是ASP.NET中提供的重要特性之一,对于程序员来讲,了解ASP.NET缓存的工作原理对于其设计程序是非常有用的. ASP.NET需要被缓存的对象多种多样,包括从数据库中提取出来的数据,以及aspx页面生成的静态页,甚至是编译好的程序集.合理利用缓存能让ASP.NET的性能大幅提升,下面将对ASP.NET中的缓存机制进行简单概述. 缓存的分类 在ASP.NET中,大部分缓存机制是保存在cache对象中,也就是服务器内存的一部分.当用户请求数据时,如果数据已经被缓

一起谈.NET技术,ASP.NET伪静态的实现及伪静态的意义

一.伪静态的用处 有些用户觉得,伪静态和真静态实际被收录量会相差很大,其实不然,从你个人角度,你去判断一下一个帖子到底是真静态还是伪静态?估计很难看得出,因为所谓静态的意思,就是地址中不带问号,不带问号的就是静态,管他是真的还是伪的?搜索引擎看得出吗?所以说,其实不论是真的还是伪的,其实对于搜索引擎来说都是一样的,搜索引擎没有说,你这个是伪的,我不收录你. 追根究底来说,为什么搜索引擎会不收录带问号的网址?因为搜索引擎怕由于问号而进入死循环,称为"搜索机器人陷阱(Spidertraps)&quo

一起谈.NET技术,ASP.NET缓存简介

概述 缓存学术一些的解释是"将常用数据放入易于读取的地方以提高性能".而对于Asp.net来说,需要被缓存的对象多种多样,包括从数据库中提取出来的数据,以及aspx页面生成的静态页,甚至是编译好的程序集.合理利用缓存能让Asp.net的性能大幅提升,下面将对Asp.net中的缓存机制进行简单概述. 缓存的分类 在Asp.net中,大部分缓存机制是保存在cache对象中,也就是服务器内存的一部分.当用户请求数据时,如果数据已经被缓存,则用户所提取的数据直接从服务端返回,而不是从数据库等底

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

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