C# 4.0 MemoryCache - how to evict dependent cache entries when changes are made to their dependencies

c# caching best practices
c# memorycache example
in-memory cache implementation in c#
microsoft.extensions.caching.memory example
imemorycache
c# cache data from database
c# disk cache
unable to resolve service for type 'microsoft extensions caching memory imemorycache

I am attempting to evict entries from a MemoryCache when changes are made to other entries on which they are dependent. This is being set up by creating cache entry change monitors for the dependencies on the dependent keys:

public bool AddToCache(string key, object dataItem, 
    DateTimeOffset absoluteExpiration, IEnumerable<string> dependencyKeys)
{
    bool result = false;

    if (!string.IsNullOrWhiteSpace(key) && dataItem != null)
    {
        CacheItemPolicy policy = new CacheItemPolicy {
            AbsoluteExpiration = absoluteExpiration
        };

        if (masterKeys != null && masterKeys.Any())
        {
            policy.ChangeMonitors.Add(
                this.provider.Cache.
                    CreateCacheEntryChangeMonitor(dependencyKeys));

            foreach (ChangeMonitor monitor in policy.ChangeMonitors)
            {
                monitor.NotifyOnChanged(this.OnDependencyChanged);
            }
        }

        result = this.provider.Cache.Add(key, dataItem, policy);
    }

    return result;
}

The OnChangedCallBack method is this:

private void OnDependencyChanged(object state)
{
    // what do I do here as "state" is always null?
}

The items are added to the cache as intended, and the OnDependencyChanged method is called as expected when a change is made to a monitored key, however the "state" instance that is passed to it is always null which means that I know nothing about the cache key whose dependency has changed and can therefore not perform the planned eviction.

Have I missed something here, am I going about this all the wrong way?

The delegate that is used as a parameter in OnChangedCacheEntry is:

public delegate void OnChangedCallback(object state);

So you have to call it like this:

monitor.NotifyOnChanged(delegate {
       OnChangedCacheEntry(OnDependencyChanged(dependencyKeys)); });

And then you will have access to the dependency keys in OnDependencyChanged

private void OnDependencyChanged(object state)
{
    IEnumerable<string> dependencyKeys = (IEnumerable<string>) state;
}

In Memory Caching - ASP.NET Core Documentation, An in-memory cache is stored in the memory of a single server hosting an is a service that should be referenced from your application by Dependency Injection. To register the caching service and make it available within your app, add the file system, or programmatic tokens, evicting the entry in response to changes. Using SQL Cache Dependencies (C#) 05/30/2007; 25 minutes to read +1; In this article. by Scott Mitchell. Download Code or Download PDF. The simplest caching strategy is to allow cached data to expire after a specified period of time.

I know it's an old thread, but here's what I have and it seems to work.

...

if (dependencies != null)
{
    var monitor = MemoryCache.Default.CreateCacheEntryChangeMonitor(dependencies);
    monitor.NotifyOnChanged(delegate { OnChangedCallback(dependencies); });
    policy.ChangeMonitors.Add(monitor);
}

...

private static void OnChangedCallback(object state)
{
    var keys = (IEnumerable<string>) state;
    if (keys != null)
        Logger.InfoFormat("callback - {0}", string.Join("|", keys.ToArray()));
    else
        Logger.InfoFormat("callback - null");
}

The dependencies parameter in OnChangedCallback(dependencies) is what's missing from original post.

Cache in-memory in ASP.NET Core, Caching works best with data that changes infrequently and is NET 4.x to ASP. Using a shared memory cache from Dependency Injection and Request the IMemoryCache instance in the constructor: C# Copy When this token fires it removes the entry immediately and fires the eviction callbacks: C# Adds a cache entry into the cache using the specified CacheItem instance and details about how to evict the entry. Add OrGet Existing (String, Object, Cache Item Policy, String) Inserts a cache entry into the cache using the specified key and value and the specified details for how it is to be evicted.

Assuming all you want to do is evict dependent entries, as OP stated, you don't need to worry about NotifyOnChanged. This is all you need:

public bool AddToCache(string key, object dataItem,
    DateTimeOffset absoluteExpiration, IEnumerable<string> dependencyKeys)
{
    CacheItemPolicy policy = new CacheItemPolicy();
    policy.AbsoluteExpiration = absoluteExpiration;

    ChangeMonitor monitor = MemoryCache.Default.CreateCacheEntryChangeMonitor(dependencyKeys);
    policy.ChangeMonitors.Add(monitor);

    return MemoryCache.Default.Add(key, dataItem, policy);
}

System.Runtime.Caching Namespace, Represents a set of eviction and expiration details for a specific cache entry. ChangeMonitor. Provides a base class for a derived custom type that monitors� c#. Score 0. Posts 2. 0 C# 4.0 MemoryCache - how to evict dependent cache entries when changes are made to their dependencies Nov 5 '19.

Cache Implementations in C# .NET, Data that constantly changes, like the current machine's time shouldn't be In- Memory Cache is used for when you want to implement cache in a single process. To handle these problems, cache frameworks have Eviction policies ( aka It can be easily injected into Asp .NET Core's dependency injection mechanism. Examples. The following example shows how to create an in-memory cache item that monitors the path for a text file. The cache creates a CacheItemPolicy object and sets the AbsoluteExpiration property to evict the cache after 60 seconds.

10 things to know about in-memory caching in ASP.NET Core , This way the default implementation of an in-memory cache - an In-memory caching uses dependency injection to inject the cache object The above code sets a cache entry in the Index() action. This is done using Set<T>() method of IMemoryCache. Offline installation of VS2017 in 4 Easy Steps. Cache dependencies. The following sample shows how to expire a cache entry if a dependent entry expires. A CancellationChangeToken is added to the cached item. When Cancel is called on the CancellationTokenSource, both cache entries are evicted.

c#, C# 4.0 MemoryCache - how to evict dependent cache entries when changes are made to their dependencies. I am attempting to evict entries from a� Like other Set method overloads, the Set method always puts a cache value in the cache, regardless whether a matching entry already exists. If the specified entry does not exist in the cache, a new cache entry is inserted. If the specified entry exists, it is updated. Removing an entry triggers any associated change monitors.

Comments
  • Hi Jibberish, you marked the right answer follwoing, but I still cant understand why the answer is right, I even cant found where is OnChangedCacheEntry... I am faced the same problem, state always null, could you help explain a little more? thanks!