我可以找到一个remove
方法,通过其键从IMemoryCache
中删除对象。有没有办法重置整个缓存并删除所有对象?
编辑:
How to clear MemoryCache?
链接中提供的Dispose方法在asp.net 5中给出了一个例外。ObjectDisposedException: Cannot access a disposed object.
Object name: 'Microsoft.Extensions.Caching.Memory.MemoryCache'.
答案 0 :(得分:18)
https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory 部分缓存依赖关系
使用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();
}
}
答案 1 :(得分:2)
RC1的答案是你不能从我读过的内容开箱即用(我在GitHub上读过,可能有一种创建触发器的方法来促进这种情况的发生) 。
目前,您可以获得Get,Set和Remove。我认为你的选择是:
https://github.com/blakepell/Caching/commit/165ae5ec13cc51c44a6007d6b88bd9c567e1d724
昨晚我发布了这个问题试图弄清楚是否有一种很好的方法可以专门检查缓存中的内容(问我们为什么没有办法)。如果你不问你永远不会知道它是否重要,所以我想为什么不这样做。
答案 2 :(得分:2)
有很多方法可以做到这一点。如果您拥有正确的IMemoryCache,则可以使用Compact(1.0)
,否则此黑客可以使用:
此代码将起作用(在单元测试中以及.NET core 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);
答案 3 :(得分:1)
我的解决方案是将缓存中所有项目的新过期日期设置为1毫秒。然后它们过期,因此缓存刷新。
答案 4 :(得分:0)
我的解决方案是创建一个包装器,该包装器将现有的一些方法重新公开,并通过用全新的MemoryCache对象替换添加缺少的方法。 对我来说很好。 代码如下:
cert-manager-webhook
答案 5 :(得分:0)
如果您使用标准的MemoryCache,则此代码可以提供帮助。 文档:https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-3.1#memorycachecompact
_cache.Compact(1.0);
答案 6 :(得分:0)
我通过在 IMemoryCache 周围创建一个 FlushableMemoryCache 单例来解决它,它跟踪当前存储在缓存中的键,然后可以遍历它们以将它们全部刷新:
public interface IFlushableMemoryCache
{
void Set<T>(string cacheId, object key, T value);
bool TryGetValue<T>(object key, out T value);
void Remove(string cacheId, object key);
void Flush(string cacheId);
}
public class FlushableMemoryCache : IFlushableMemoryCache
{
private readonly IMemoryCache _memoryCache;
private readonly IDictionary<string, HashSet<object>> _keyDictionary;
public FlushableMemoryCache(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
_keyDictionary = new Dictionary<string, HashSet<object>>();
}
public void Set<T>(string cacheId, object key, T value)
{
_memoryCache.Set(key, value);
if (_keyDictionary.ContainsKey(cacheId))
{
if (!_keyDictionary[cacheId].Contains(key))
{
_keyDictionary[cacheId].Add(key);
}
}
else
{
_keyDictionary.Add(cacheId, new HashSet<object>(new[] { key }));
}
}
public bool TryGetValue<T>(object key, out T value)
{
return _memoryCache.TryGetValue(key, out value);
}
public void Remove(string cacheId, object key)
{
_memoryCache.Remove(key);
if (_keyDictionary.ContainsKey(cacheId) && _keyDictionary[cacheId].Contains(key))
{
_keyDictionary[cacheId].Remove(key);
}
}
public void Flush(string cacheId)
{
foreach (var key in _keyDictionary[cacheId])
{
_memoryCache.Remove(key);
}
_keyDictionary[cacheId] = new HashSet<object>();
}
}
使用此功能的服务需要提供该服务独有的 cacheId
。这允许 Flush
只清除与特定服务相关的键,而不是缓存中的所有内容!
答案 7 :(得分:0)
IMemoryCache _MemoryCache;
public CacheManager(IMemoryCache MemoryCache)
{
_MemoryCache = MemoryCache;
}
public void Clear()
{
_MemoryCache.Dispose();
_MemoryCache = new MemoryCache(new MemoryCacheOptions());
}