如何从ASP.NET核心中的IMemoryCache中删除所有对象(重置)

问题描述 投票:17回答:4

我可以找到一个remove方法,通过它的键从IMemoryCache中删除一个对象。有没有办法重置整个缓存并删除所有对象?

编辑:

How to clear MemoryCache?链接中提供的Dispose方法在asp.net 5. ObjectDisposedException: Cannot access a disposed object. Object name: 'Microsoft.Extensions.Caching.Memory.MemoryCache'. 中给了我一个例外

c# asp.net-core asp.net-core-mvc
4个回答
19
投票

https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory Section Cache依赖项

使用CancellationTokenSource允许将多个缓存条目作为一个组逐出

这段代码对我有用:

public class CacheProvider 
{
    private static CancellationTokenSource _resetCacheToken = new CancellationTokenSource();
    private readonly IMemoryCache _innerCache;

    /* other methods and constructor removed for brevity */

    public T Set<T>(object key, T value) 
    {
        /* some other code removed for brevity */
        var options = new MemoryCacheEntryOptions().SetPriority(CacheItemPriority.Normal).SetAbsoluteExpiration(typeExpiration);
        options.AddExpirationToken(new CancellationChangeToken(_resetCacheToken.Token));

        _innerCache.Set(CreateKey(type, key), value, options);

        return value;
    }

    public void Reset()
    {
        if (_resetCacheToken != null && !_resetCacheToken.IsCancellationRequested && _resetCacheToken.Token.CanBeCanceled)
        {
            _resetCacheToken.Cancel();
            _resetCacheToken.Dispose();
        }

        _resetCacheToken = new CancellationTokenSource();
    }
}

2
投票

RC1的答案是,你不能从我读过的内容中做到这一点并且被告知(我在GitHub上读过,可能有一种方法可以创建触发器来促进这种情况的发生)。

目前,您将获得Get,Set和Remove。我看到你的选择:

  1. 创建一个跟踪所有密钥的缓存管理器包装,然后您可以根据需要批量删除这些项目。我不爱这个,但它会起作用。当然,如果您不是控制添加的人,那么缓存中可能存在您不知道的内容(您可以将您的计数与其数量进行比较)。如果将IMemoryCache转换为MemoryCache,则可以获取公开的Count属性。
  2. 叉组件并公开Keys和/或添加方法以删除这些项。有一个基础字典保存密钥。我做了这个,编译它,为它创建一个Nuget包然后替换RC1版本只是为了看看我是否可以(并且它工作)。不确定这是否是正确的方法,但这里是我的fork的提交,我只是添加了一个只读属性,我将键转储到对象列表(键存储为对象)。与过去的MemoryCache实现一样,如果你暴露了它们,它们在被转储后可能会过时,但是如果你只是用它们来清除所有那些那么无关紧要。

https://github.com/blakepell/Caching/commit/165ae5ec13cc51c44a6007d6b88bd9c567e1d724

我昨晚发布了这个问题,试图弄清楚是否有一个很好的方法来专门检查缓存中的内容(问为什么我们没有办法)。如果你不问你永远不会知道它是否重要,所以我想为什么不。

https://github.com/aspnet/Caching/issues/149


2
投票

有很多黑客可以做到这一点。如果你有正确的IMemoryCache,你可以使用Compact(1.0),否则这个hack有效:

此代码将起作用(在单元测试和.NET核心2.2上的生产中测试):

PropertyInfo prop = cache.GetType().GetProperty("EntriesCollection", BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Public);
object innerCache = prop.GetValue(cache);
MethodInfo clearMethod = innerCache.GetType().GetMethod("Clear", BindingFlags.Instance | BindingFlags.Public);
clearMethod.Invoke(innerCache, null);

1
投票

我的解决方案是将缓存中所有项目的新到期日期设置为1毫秒。然后他们过期,因此缓存刷新。


0
投票

我的解决方案是创建一个包装器,重新公开现有的几个方法,并通过用一个全新的方法替换MemoryCache对象来添加一个缺少的方法。工作对我来说很好。代码如下:

public interface IMyMemoryCache : IMemoryCache
{
    void Reset();
}
public class MyMemoryCache: IMyMemoryCache
{
    IMemoryCache _memoryCache;

    public MyMemoryCache()
    {
        Reset();
    }
    public void Dispose()
    {
        _memoryCache.Dispose();
    }

    public bool TryGetValue(object key, out object value)
    {
        return _memoryCache.TryGetValue(key, out value);
    }

    public ICacheEntry CreateEntry(object key)
    {
        return _memoryCache.CreateEntry(key);
    }

    public void Remove(object key)
    {
        _memoryCache.Remove(key);
    }

    public void Reset()
    {
        _memoryCache = new MemoryCache(new MemoryCacheOptions());
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.