【问题标题】:Any way to clear/flush/remove OutputCache?有什么方法可以清除/刷新/删除OutputCache?
【发布时间】:2009-02-19 13:07:08
【问题描述】:

我在我的网络用户控件 (.ascx) 上使用 OutputCache

<%@ OutputCache Duration="1000" VaryByParam="none" %>

我想在接下来的 1000 秒内保留缓存,但是当我网站上的特定页面被加载时,我想删除/刷新/刷新缓存。比如,我想在加载 MyPage.aspx 时清除缓存。我可以通过编程方式刷新缓存吗?

它只有一页被缓存,因此没有参数化版本可以刷新缓存。

提前感谢您的帮助。

【问题讨论】:

    标签: asp.net caching


    【解决方案1】:

    您可以为此使用VaryByCustom 参数。

    在您的用户控件中,您将拥有以下内容:

    <%@ OutputCache Duration="1000" VaryByParam="None" VaryByCustom="MyKey" %>
    

    然后您将覆盖 Global.asax 中的 GetVaryByCustomString 方法,如下所示:

    public override string GetVaryByCustomString(HttpContext context, string arg)
    {
        if (arg == "MyKey")
        {
            object o = context.Current.Application["MyGuid"];
            if (o == null)
            {
                o = Guid.NewGuid();
                context.Current.Application["MyGuid"] = o;
            }
            return o.ToString();
        }
        return base.GetVaryByCustomString(context, arg);
    }
    

    最后在MyPage.aspx 你会这样做:

    Application["MyGuid"] = Guid.NewGuid();
    

    这是如何工作的?

    当你的控件被缓存时,它与一个字符串相关联(当你的控件的VaryByCustom 键被传递给它时,从GetVaryByCustomString 方法返回的字符串)。

    每当随后使用该控件时,都会再次调用GetVaryByCustomString。如果返回的字符串与控件的缓存版本匹配,则使用缓存版本。

    在我们的例子中,“MyKey”被传递到GetVaryByCustomString 并返回存储在Application["MyGuid"] 中的任何内容。

    每当调用MyPage.aspx 时,它都会将Application["MyGuid"] 更改为一个新的随机值。

    下次使用您的控件时,GetVaryByCustomString 方法将返回新值,并且由于没有与该值关联的控件的缓存版本,因此将重新生成控件。 (然后控件将被缓存并与新值相关联,直到下一次调用 MyPage.aspx 等)

    有一个概述here

    【讨论】:

    • 是删除之前的副本还是保留2个?
    • 这实际上并没有从缓存中清除任何东西,只是添加了一个新的唯一键,看起来像是一个清除缓存,所以是的,现在内存中会有两个缓存数据的副本。如果您已经在网站的其他地方使用 VaryByCustom,您可能需要修改上述代码以将 GUID 附加到现有的 VaryByCustom 字符串。
    • 此方法成功。感谢您的提示。干得好。
    【解决方案2】:

    您可以使用HttpResponse.RemoveOutputCacheItemHttpResponse.AddCacheItemDependency 使输出缓存条目无效。

    【讨论】:

    • 我最终做了类似的事情:stackoverflow.com/questions/11585/…
    • 如果您的 OutputCacheProvider 不是默认值(例如,您使用的是 AppFabric 或 MemCached)这些方法将不起作用。只是提醒任何考虑他们的选择的人......我认为 VaryByCustom 答案更可取,因为它适用于任何一种情况。
    • 真的两者都可取; VaryByCustom 可以为您提供他所询问的一些内容,但如果页面的先前版本真的永远死了,再也不会被使用,您可能会通过使用 RemoveOutputCacheItem 显式驱逐它来减少缓存压力。
    【解决方案3】:

    破解一种疯狂的方法有点像大锤,但它是完全清除/刷新我发现的应用程序缓存的最简单和最有效的方法。

    只需调用:

    HttpRuntime.UnloadAppDomain();
    

    这与回收应用程序池具有相同的影响。并非在所有情况下都适用,但它肯定会完成工作。

    【讨论】:

    • 我同意。在用尽了许多不同的技术之后,这是唯一可靠的工作方法。
    • 这根本不是清除缓存的唯一可靠方法。这意味着其他机制都不起作用,这是大胆的。卸载应用程序域非常繁琐。
    【解决方案4】:

    编辑:如果您在 II6+ 上启用了内核缓存,那么您将需要遵循 Luke 的建议并使用 VaryByCustom 标头,因为清除 ASP.NET 缓存不会影响内核缓存。

    OutputCache 存储在 ASP.NET Cache 中,因此您只需调用 Cache.Remove:

    List<string> keys = new List<string>();
    
    foreach(string key in HttpRuntime.Cache)
    {
        keys.Add(key);
    }
    
    foreach(string key in keys)
    {
        Cache.Remove(key);
    }
    

    但是,这将删除所有缓存条目,包括您的代码添加的自定义条目。

    【讨论】:

    • 你确定这是同一个缓存吗?我认为 OutputCache 是 IIS 的东西。我认为这行不通。
    • 在 IIS7 中默认启用内核缓存:technet.microsoft.com/en-us/library/cc731903(v=ws.10).aspx 因此,如果您从未配置过此功能,则已启用它。
    • 这只会删除自定义缓存项目,而不是缓存的网址/页面。
    【解决方案5】:

    受其他帖子的启发,下面的 sn-p 使用反射成功删除了 asp.net 中OutputCache 缓存的每个页面:

            public static void ClearOutputCache()
            {
    
                var runtimeType = typeof(HttpRuntime);
    
                var ci = runtimeType.GetProperty(
                   "CacheInternal",
                   BindingFlags.NonPublic | BindingFlags.Static);
    
                var cache = ci.GetValue(ci, new object[0]);
    
                var cachesInfo = cache.GetType().GetField(
                    "_caches",
                    BindingFlags.NonPublic | BindingFlags.Instance);
                var cacheEntries = cachesInfo.GetValue(cache);
    
                var outputCacheEntries = new List<object>();
    
                foreach (Object singleCache in cacheEntries as Array)
                {
                    var singleCacheInfo =
                    singleCache.GetType().GetField("_entries",
                       BindingFlags.NonPublic | BindingFlags.Instance);
                    var entries = singleCacheInfo.GetValue(singleCache);
    
                    foreach (DictionaryEntry cacheEntry in entries as Hashtable)
                    {
                        var cacheEntryInfo = cacheEntry.Value.GetType().GetField("_value",
                           BindingFlags.NonPublic | BindingFlags.Instance);
                        var value = cacheEntryInfo.GetValue(cacheEntry.Value);
                        if (value.GetType().Name == "CachedRawResponse")
                        {
                            var key = (string)cacheEntry.Value.GetType().BaseType.GetField("_key", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(cacheEntry.Value);
                            key = key.Substring(key.IndexOf("/"));
                            outputCacheEntries.Add(key);
                        }
                    }
                }
                foreach (string key in outputCacheEntries)
                {  
                    HttpResponse.RemoveOutputCacheItem(key);
                }
            }
    

    【讨论】:

    • 这个答案对我帮助很大。能够遍历缓存并获取密钥向我展示了我所需要的。谢谢。
    • 我尝试使用代码,但出现运行时错误 System.NullReferenceException: var cacheEntries = cachesInfo.GetValue(cache);
    【解决方案6】:

    由于this answer 不再起作用,并且this answer 仅清除自定义缓存项(而不是缓存中存储的页面/MVC 操作),我挖掘了 ASP.NET 参考源代码并得出了以下结论:

    public static void ClearAllCache()
    {
        var runtimeType = typeof(System.Web.Caching.Cache);
    
        var ci = runtimeType.GetProperty(
           "InternalCache",
           BindingFlags.Instance | BindingFlags.NonPublic);
    
        var cache = ci.GetValue(HttpRuntime.Cache) as System.Web.Caching.CacheStoreProvider;
        enumerator = cache.GetEnumerator();
        while (enumerator.MoveNext())
        {
            keys.Add(enumerator.Key.ToString());
        }
        foreach (string key in keys)
        {
            cache.Remove(key);
        }
    }
    

    更多信息在我的博文here

    【讨论】:

      【解决方案7】:

      您可以添加 HttpResponse.RemoveOutputCacheItem("/YourCachePageName.aspx");页面的页面加载事件中的代码行,您希望缓存页面的缓存关闭。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 1970-01-01
        • 2016-01-20
        • 2010-11-28
        • 1970-01-01
        • 2012-05-10
        • 1970-01-01
        相关资源
        最近更新 更多