The DotNet Core Microsoft.Extensions.Caching.Memory lacks the ability to easily remove groups of items from the cache. This is a know limitation which apparently there is no interest in addressing.
The project is published to NuGet
- NET Standard + Platform Extensions,Version=v2.0
- NET Core + Platform Extensions,Version=v2.0
- Microsoft.Extensions.Caching.Memory (>= 2.0.0)
- Microsoft.Extensions.DependencyInjection (>= 2.0.0)
- When adding items to the cache, specify the group they belong to
- Remove a group of cached items by group name
- Remove all items in the cache
- Specify the item's cache lifetime in seconds when adding an item to the cache
- Synchronous and Asynchonous factory lamda functions
Please feel free to make a pull request. :)
- Unit tests
- Query the cache status?
Run the included example dotnet console application which demonstrates a simulated database of products where accessing the database is an expensive operation, so these query results are meant to be cached in a product provider.
When a change is made to the product database, the cache has items removed from that product's categories, so when future requests for product lists will pick up the new product immediately.
The console output shows that the first time the beer list is queries, an expensive database operation happens, and subsequent request are served from the cache.
Once a new item is added to the category, the cache for that category becomes invalidated, and the next reqeust for the beer list correctly results in another expensive database hit.
Install from nuget by running
dotnet add package GeekyMonkey.DotNetCoreMemoryCacheService
In your application startup, register the following two services with the dependency injection system.
// register memory cach service
services.AddMemoryCache();
services.AddSingleton<MemoryCacheService, MemoryCacheService>();
The first one is the MemoryCache service included in DotNet Core. The second is our extension library. These are both singletons or else what's the point. ;)
Probably best to do this sort of thing inside of a data provider class, but that's not a hard requirement.
With your instance of the MemoryCacheService call GetOrCreate<MyItemType>()
. The parameters are
- string Cache Group (used for later removing groups of items)
- string Unique cache key
- double Seconds before the item automatically is removed from the cache
- (cacheEntry)=>MyItemType A factory functon that will generate or retrieve your value if it is not in the cache. This is where you find the data in a databaes, or call an API to download the data.
Example:
MemoryCacheService.GetOrCreate<List<ProductModel>>(
$"MyCacheGroup", $"MyCacheKey",
60, (cacheEntry) => {
// Not in the cache - get from the database
return DownloadMyProductData();
});
There is also a GetOrCreateAsync<>()
function that works exactly as GetOrCreate<>()
except that it runs asyncrounsly and needs to be awaited. Use this wherever possible.
When a change is saved to the database, and you want your users to see this new data, use one of the below functions for the different ranges of item(s) to be deleted from cache. Note that these are not refreshed back into the cach until the next time they are requested.
Boring! You could already do this. But maybe this is your thing. I'm not going to judge. The RemoveItem(string cacheKey)
is there for this sort of thing.
When you call ClearCacheGroup(string groupName)
, any item still in the cache that's registered with that group will be removed immediately.
The nuclear option. There is a ClearAll()
that removes all of the cache groups.
If deploying to a server farm and you want to stick with in-memory cache, be sure to configure the load balancer to use sticky sessions. Otherwise you should use a distributed cache.
- Got a problem or suggestion? Use the Issues feature to let me know.
- Feel like your own code changes would be helpful? Issue a Pull Request.
- Did I save you some time? Feeling thankfull? Go on, buy me a beer. 🍺