使asp.net mvc输出缓存的部分无效 - 具有不同的粒度级别

时间:2010-08-13 18:45:40

标签: asp.net asp.net-mvc outputcache

我对HttpResponse.RemoveOutputCacheItem()调用提供的粒度感到有点困惑。我有兴趣在动态生成的图像上执行一些输出缓存,并希望至少使用参数来改变输出缓存(为了参数的缘故,我们称它们为'id'和'size'。)

所以,例如:

/Image/User?id=1
/Image/User?id=1&size=1
/Image/User?id=1&size=2

将单独缓存。

当给定用户改变他们的照片时;我想要使​​该用户ID的所有输出缓存项无效(无论大小)。 This question回答了我关于单个特定参数的问题。但是..如果不考虑大小参数,我将如何为用户刷新所有缓存的响应? (我们假设我不会提前知道'size'的所有可能值。)

我最喜欢这样的事情:

HttpResponse.RemoveOutputCacheItem("/Image/User?id=1&size=*"); //wishful thinking

有人能指出我正确的方向吗?

修改

@JcMalta提出了一个很有前途的解决方案,但是我找不到为输出缓存中的项目公开的适当集合。一个可行的解决方案可能包括类似于他提出的操作,如果它存在于某处。

2 个答案:

答案 0 :(得分:3)

输出缓存具有“缓存依赖关系”的概念,可能就是您要查找的内容。

.NET具有FileCacheDependency,这意味着如果磁盘上的文件发生更改,则缓存项会自动失效,而当MSSQL数据库中的数据发生更改时,会使SqlCacheDependency失效。您还可以编写自定义缓存依赖项。

HttpResponse有一堆名为Add * Dependency / ies的方法让你使用它。

例如,如果您的图片是基于磁盘上的文件,那么为调整大小的图像提供服务的处理程序可能会说:

HttpResponse.AddFileDependency(@"C:\images\user" + userId + ".jpg");

这会为您的响应注册一个依赖项。当您的响应添加到输出缓存时,任何依赖项都会随之发生。当依赖项更改时,缓存项将自动失效。

如果您的图像基于文件或SQL数据,这可能会为您提供开箱即用的功能。

您还可以使用HttpResponse.AddCacheItemDependency使一个缓存项依赖于另一个缓存项。如果您知道原始图像URL“/ Image / User?id = 1”将始终被缓存,那么您可以使调整大小的图像依赖于原始图像,并且原始图像上的HttpResponse.RemoveOutputCacheItem()将清除所有这些图像。如果原始图像并不总是被缓存(也许没有人请求原始图像,只有缩略图),那么我认为这不会起作用。

内置缓存依赖项工作的原因是Windows和SQL Server都有内置API来通知文件或数据的更改。内置缓存依赖项是围绕它们的包装器。但如果这些都不合适,那么你的最后一种方法就是为了你自己的目的而实现类似的东西。

基本思想(未经测试)是子类CacheDependency,我们称之为PictureCacheDependency。

您需要设置某种侦听器/观察者模式,以便在用户编辑其图片时,图片编辑代码可以告知任何相关的PictureCacheDependency对象图片已更改。当发生这种情况时,PictureCacheDependency应该调用base.NotifyDependencyChanged,框架将负责其余的工作。

您可能将PictureCacheDependency构造函数注册在静态事件字典中,并使用用户ID作为键。无论你接近它,一定要覆盖CacheDependency.DependencyDispose来释放任何引用,否则你会泄漏内存。

答案 1 :(得分:1)

真的,这不是我的头脑......但也许是在正确的方向:

public void ClearCache( string myImagePrefix)
{
    var cache = System.Web.HttpContext.Current.Cache;

    IDictionaryEnumerator enumerator = cache.GetEnumerator();

    while (enumerator.MoveNext())
    {
        string key = enumerator.Key.ToString();
        if( key.StartsWith( myImagePrefix)
           cache.Remove(key);
    }
}