alastairtree / LazyCache

An easy to use thread safe in-memory caching service with a simple developer friendly API for c#
https://nuget.org/packages/LazyCache
MIT License
1.72k stars 159 forks source link

Invalidate/Clear a cache instance #6

Closed akrohn closed 8 years ago

akrohn commented 8 years ago

I can remove an cache item, but how do I clear the whole cache. I need it after a database deployment in an update scenario where all has to be loaded from the database first and the cache has to be invalidated.

Cheers

alastairtree commented 8 years ago

Assuming you are using the default configuration then underneath the items are stored in the default MemoryCache. In which case you would need to iterate over each of the keys in the memory cache and remove the cache item. Neither LazyCache nor MemoryCache provide a built in in way to remove all items, because usually this need indicates another issue - for example should you instead be disposing instances of the underlying cache and recreating them? Or perhaps you don't need to remove all the items and are just hacking round a more targeted removal strategy? To get the most benefits from the cache, it is best not to throw away all the data stored in it if you can. Hope that helps?

akrohn commented 8 years ago

Thanks for your suggestions.

How do I access the underlying memory cache to dispose it and instantiate a new one? Seems there is no properties "keys" or "memorycache" that I can use for a "foreach" loop. Searched your wiki, but didn't found an example.

Cheers

alastairtree commented 8 years ago

You would need to either create an instance of MemoryCache yourself and pass it into the LazyCache constructor to have access to the instance, or use MemoryCache.Default property which points to the current instance if you are using the default LazyCache behaviour.

alastairtree commented 8 years ago

The upcoming version of lazy cache exposes an ObjectCache property where you can access the instance of the underlying cache. You would then need to dispose that (or iterate over the keys and remove them however this is not recommended by microsoft as it is expensive) and recreate your caching service instance with a new object cache constructor parameter.

akrohn commented 8 years ago

Sounds great!

alastairtree commented 8 years ago

LazyCache 0.7 now exposes the underlying ObjectCache - see https://github.com/alastairtree/LazyCache/blob/master/LazyCache/IAppCache.cs.

This would allow you to iterate over the keys and remove entries if you really need to clear the cache that way, however I would still recommend managing your own instance of MemoryCache and recreating that to clear the cache. As such I am now closing this issue as done.

akrohn commented 8 years ago

Hello,

got your new version and tried to dispose the cache by using the new ObjectCache property. From my understanding this is not possible, because the class "ObjectCache" is abstract and cannot be used in any way. There are no properties or methods I can use on this instance.

See also http://stackoverflow.com/questions/14232130/what-is-difference-between-memorycache-vs-objectcache-in-net-4-0

Why didn't you expose the MemoryCache instance?

Cheers.

Update: Seems I forgot to add a reference to System.Runtime.Caching assembly. Sigh. Update 2: ObjectCache is not disposable. MemoryCache is. Update 3: Found an interesting concept to clear only a subset of keys. Maybe this is useful for a new version of LazyCache. (http://stackoverflow.com/questions/4183270/how-to-clear-the-net-4-memorycache/22388943#comment34789210_22388943)

akrohn commented 8 years ago

Damned. I don't get it.

I have declared various instances of LazyCache for different types of caches, because there is currently no support for regions.


cache1 = new CachingService() { DefaultCacheDuration = DefaultCacheDuration };
cache2 = new CachingService() { DefaultCacheDuration = DefaultCacheDuration };

So now I just want to remove all items of instance cache1. How do I do that by using the new ObjectCache property or is there any other way? ObjectCache has no "select" method to iterate over all elements.

Cheers.

akrohn commented 7 years ago

No ideas yet? So I would have to look for other caching packages ... but I dont want to. Usage is great, but clearing the cache not.

SamJongenelen commented 7 years ago
private void ClearCache()
        {
            var cacheKeys = _cachingService.ObjectCache.Where(kvp => kvp.Key.Equals("MyCacheKey"))
                .Select(kvp => kvp.Key);
            foreach (var cacheKey in cacheKeys)
            {
                _cachingService.ObjectCache.Remove(cacheKey);
            }
        }

Mind you, we only use this code for invalidating the cache for test automation. I wouldn't recommend this as a runtime solution. You could refactor this as an extension method as well

wsrinivas commented 5 years ago

For my production environment, I had to recycle the Application pool and the cache was build again, with the new data from my production database.

alastairtree commented 5 years ago

I think you would need to cast ObjectCache to MemoryCache and then dispose it, or create the MemoryCache yourself rathter than relying on the default instance. To clear everything you would need to dispose of the underlying cache and then create a new CachingService with a new underlying MemoryCache.

petrosmm commented 5 years ago
private void ClearCache()
        {
            var cacheKeys = _cachingService.ObjectCache.Where(kvp => kvp.Key.Equals("MyCacheKey"))
                .Select(kvp => kvp.Key);
            foreach (var cacheKey in cacheKeys)
            {
                _cachingService.ObjectCache.Remove(cacheKey);
            }
        }

Mind you, we only use this code for invalidating the cache for test automation. I wouldn't recommend this as a runtime solution. You could refactor this as an extension method as well

Hi @SamJongenelen, Would you mind elaborating as to why this cannot be recommend as a runtime solution?

SamJongenelen commented 5 years ago

@petrosmm well, concurrency, for one thing. @alastairtree had described a cleaner way to do it IMO

petrosmm commented 5 years ago

@petrosmm well, concurrency, for one thing. @alastairtree had described a cleaner way to do it IMO

ahh okay, found it here