Home > Blockchain >  Increase counter inside IMemoryCache
Increase counter inside IMemoryCache

Time:11-05

I have the following situation:

//IMemoryCache is injected into class and into field _cache
public void IncreaseCounter(string key){

     int currectCount = _cache.Get<int>(key)   1;
     _cache.Set<int>(key, currentCount);
}

However I am aware that this is not the best method to do it. I would also like to check if the key does exist, if it does not, the counter should be 0 and then increased to 1.

How would I do this ? I know of the method GetOrCreate(object, Func<>) but I don't know how to implement this.

CodePudding user response:

GetOrCreate basically works like this:

   int currentCount = _cache.GetOrCreate(key, _ => 0); // pass key and 
                                                       // "new item factory"
   // now, if key exists, it will return the cached value
   // if it does not exist, it will 
   // - create a new entry,
   // - execute the passed-in factory function und set the returned value in cache,
   // - return the result of the passed-in factory
   _cache.Set(key, currentCount 1);

The expected factory must be a Func<ICacheEntry, TItem> which translate to delegate of this form: TItem FunctionName(ICacheEntry entry). So, a function that takes a parammeter of type ICacheEntry and returns whatever type your values shall be.

_ => 0 matches this in that it is a Func, that ignores the input param and just returns 0, which should be enough for the use case from the question.

See an Example in Fiddle

using System;
using Microsoft.Extensions.Caching.Memory;
                    
public class Program
{
    public static void Main()
    {
        IMemoryCache cache = new MemoryCache(new MemoryCacheOptions());
        object key = new object();
        
        Console.WriteLine("{0}", cache.TryGetValue(key, out int val)?val:"key not found");
        
        Incr(key, cache);
        Console.WriteLine(cache.Get(key));
        
        Incr(key, cache);
        Console.WriteLine(cache.Get(key));
    }
    
    public static void Incr(object key, IMemoryCache cache)
    {
        int currentValue = cache.GetOrCreate(key, _ => 0);
        cache.Set(key, currentValue 1);
    }
}

Produces

key not found
1
2

Just for your information - not relevant to the specific use case in question:

Mind that I used the "ignore" ( _ => ) here. If you need to, you can actually use information from the newly created cache entry from within the factory (or set values on it):

int currentValue = cache.GetOrCreate(key, entry => DoDBLookup(entry.Key));

for example, if you wanted to read-through to a database. Or set expiry, compute intial value based on key, etc ...

  • Related