On first look this looks duplicate of this question, but I am not asking how to clear cache for EF.
How can I clear entire cache set by IMemoryCache
interface?
public CacheService(IMemoryCache memoryCache)
{
this._memoryCache = memoryCache;
}
public async Task<List<string>> GetCacheItem()
{
if (!this._memoryCache.TryGetValue("Something", out List<string> list))
{
list= await this ...
this._memoryCache.Set("Something", list, new MemoryCacheEntryOptions().SetPriority(CacheItemPriority.NeverRemove));
}
return list;
}
This is just an example. I have many classes/methods that are storing values to cache. Now I need to remove them all.
My keys are, in some cases, created dynamically, so I don't know which keys I need to remove. Clear would be perfect.
I could write my own interface and class which would internally use IMemoryCache
, but this seems overkill. Is there any easier options?
I couldn't find any good solutions so, I wrote my own.
In SamiAl90 solution (answer) I missed all properties from ICacheEntry interface.
Internally it uses IMemoryCache.
Use case is exactly the same with 2 additional features:
You have to register a singleton:
serviceCollection.AddSingleton<IMyCache, MyMemoryCache>();
Use case:
public MyController(IMyCache cache)
{
this._cache = cache;
}
[HttpPut]
public IActionResult ClearCache()
{
this._cache.Clear();
return new JsonResult(true);
}
[HttpGet]
public IActionResult ListCache()
{
var result = this._cache.Select(t => new
{
Key = t.Key,
Value = t.Value
}).ToArray();
return new JsonResult(result);
}
Source:
public interface IMyCache : IEnumerable<KeyValuePair<object, object>>, IMemoryCache
{
/// <summary>
/// Clears all cache entries.
/// </summary>
void Clear();
}
public class MyMemoryCache : IMyCache
{
private readonly IMemoryCache _memoryCache;
private readonly ConcurrentDictionary<object, ICacheEntry> _cacheEntries = new ConcurrentDictionary<object, ICacheEntry>();
public MyMemoryCache(IMemoryCache memoryCache)
{
this._memoryCache = memoryCache;
}
public void Dispose()
{
this._memoryCache.Dispose();
}
private void PostEvictionCallback(object key, object value, EvictionReason reason, object state)
{
if (reason != EvictionReason.Replaced)
this._cacheEntries.TryRemove(key, out var _);
}
/// <inheritdoc cref="IMemoryCache.TryGetValue"/>
public bool TryGetValue(object key, out object value)
{
return this._memoryCache.TryGetValue(key, out value);
}
/// <summary>
/// Create or overwrite an entry in the cache and add key to Dictionary.
/// </summary>
/// <param name="key">An object identifying the entry.</param>
/// <returns>The newly created <see cref="T:Microsoft.Extensions.Caching.Memory.ICacheEntry" /> instance.</returns>
public ICacheEntry CreateEntry(object key)
{
var entry = this._memoryCache.CreateEntry(key);
entry.RegisterPostEvictionCallback(this.PostEvictionCallback);
this._cacheEntries.AddOrUpdate(key, entry, (o, cacheEntry) =>
{
cacheEntry.Value = entry;
return cacheEntry;
});
return entry;
}
/// <inheritdoc cref="IMemoryCache.Remove"/>
public void Remove(object key)
{
this._memoryCache.Remove(key);
}
/// <inheritdoc cref="IMyCache.Clear"/>
public void Clear()
{
foreach (var cacheEntry in this._cacheEntries.Keys.ToList())
this._memoryCache.Remove(cacheEntry);
}
public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
{
return this._cacheEntries.Select(pair => new KeyValuePair<object, object>(pair.Key, pair.Value.Value)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
/// <summary>
/// Gets keys of all items in MemoryCache.
/// </summary>
public IEnumerator<object> Keys => this._cacheEntries.Keys.GetEnumerator();
}
public static class MyMemoryCacheExtensions
{
public static T Set<T>(this IMyCache cache, object key, T value)
{
var entry = cache.CreateEntry(key);
entry.Value = value;
entry.Dispose();
return value;
}
public static T Set<T>(this IMyCache cache, object key, T value, CacheItemPriority priority)
{
var entry = cache.CreateEntry(key);
entry.Priority = priority;
entry.Value = value;
entry.Dispose();
return value;
}
public static T Set<T>(this IMyCache cache, object key, T value, DateTimeOffset absoluteExpiration)
{
var entry = cache.CreateEntry(key);
entry.AbsoluteExpiration = absoluteExpiration;
entry.Value = value;
entry.Dispose();
return value;
}
public static T Set<T>(this IMyCache cache, object key, T value, TimeSpan absoluteExpirationRelativeToNow)
{
var entry = cache.CreateEntry(key);
entry.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow;
entry.Value = value;
entry.Dispose();
return value;
}
public static T Set<T>(this IMyCache cache, object key, T value, MemoryCacheEntryOptions options)
{
using (var entry = cache.CreateEntry(key))
{
if (options != null)
entry.SetOptions(options);
entry.Value = value;
}
return value;
}
public static TItem GetOrCreate<TItem>(this IMyCache cache, object key, Func<ICacheEntry, TItem> factory)
{
if (!cache.TryGetValue(key, out var result))
{
var entry = cache.CreateEntry(key);
result = factory(entry);
entry.SetValue(result);
entry.Dispose();
}
return (TItem)result;
}
public static async Task<TItem> GetOrCreateAsync<TItem>(this IMyCache cache, object key, Func<ICacheEntry, Task<TItem>> factory)
{
if (!cache.TryGetValue(key, out object result))
{
var entry = cache.CreateEntry(key);
result = await factory(entry);
entry.SetValue(result);
entry.Dispose();
}
return (TItem)result;
}
}