Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate through MemoryCache in asp.net core?

There's no available method in IMemoryCache that allows to iterate through each cached item. My project is small, I don't want to use other options like Redis.

namepsace    Microsoft.Extensions.Caching.Memory{
        public static class CacheExtensions
    {
        public static object Get(this IMemoryCache cache, object key);
        public static TItem Get<TItem>(this IMemoryCache cache, object key);
        public static TItem GetOrCreate<TItem>(this IMemoryCache cache, object key, Func<ICacheEntry, TItem> factory);
        [AsyncStateMachine(typeof(CacheExtensions.<GetOrCreateAsync>d__9<>))]
        public static Task<TItem> GetOrCreateAsync<TItem>(this IMemoryCache cache, object key, Func<ICacheEntry, Task<TItem>> factory);
        public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value);
        public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value, DateTimeOffset absoluteExpiration);
        public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value, TimeSpan absoluteExpirationRelativeToNow);
        public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value, IChangeToken expirationToken);
        public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value, MemoryCacheEntryOptions options);
        public static bool TryGetValue<TItem>(this IMemoryCache cache, object key, out TItem value);
    }
}

https://github.com/aspnet/Caching/blob/dev/src/Microsoft.Extensions.Caching.Memory/MemoryCache.cs

like image 676
nam vo Avatar asked Apr 28 '17 06:04

nam vo


2 Answers

You should cache two type of items.

  1. You cache your properties as they are, abc.xyz-{0}.
  2. Second cache a list of property under the main key name, abc.xyz

Sample Code:

cache.Set("abc.xyz-name", name, TimeSpan.FromMinutes(30));
cache.Set("abc.xyz-lastname", lastname, TimeSpan.FromMinutes(30));
cache.Set("abc.xyz-birthday", birthday, TimeSpan.FromMinutes(30));
cache.Set("abc.xyz", new List<string> { "abc.xyz-name", "abc.xyz-lastname", "abc.xyz-birthday" }, TimeSpan.FromMinutes(30));

and when deleting:

var keys = cache.Get<List<string>>("abc.xyz");
foreach(var key in keys)
    cache.Remove(key);
cache.remove("abc.xyz");

Most of the services use IDistributedCache (in your case MemoryDistributedCache when registered - which again injects IMemoryCache which is MemoryCache class).

In a distributed cache you can't iterate over all keys as there are potentially millions of keys and this would significantly reduce the performance of the cached service if you could/would iterate over it.

So the above solution is also friendly and ready for the case when you replace your memory cache with a distributed cache, such as Redis.

like image 162
Tseng Avatar answered Sep 22 '22 00:09

Tseng


For large project this is a bit an awkward way. I'd recommend you to use a wrapper class MemoryCacheManager and register it as Singleton. https://gist.github.com/vlapenkov/0a66c40221f9c56d12eb0420fb7cef77

use

_manager.Get("key", ()=>"value") // to set a key,

_manager.GetKeys() // get all keys

_manager.Remove("key") //remove one key

_manager.Clear() //remove all keys
like image 34
Lapenkov Vladimir Avatar answered Sep 21 '22 00:09

Lapenkov Vladimir