Microsoft.Extensions.Caching is a set of libraries used for caching in .NET applications. It provides various in-memory and distributed cache implementations that can be used with any .NET application, regardless of whether it’s an ASP.NET Core web application, console application, or any other type of application built with .NET.
In this article, we will discuss:
Caching is a technique used to store and retrieve frequently accessed data more efficiently. By temporarily storing a copy of the data in a cache, applications can avoid redundant and time-consuming operations, such as database queries or complex calculations. Caching can significantly enhance the performance and responsiveness of an application.
Microsoft.Extensions.Caching consists of two main components:
The MemoryCache
class provides an in-memory cache implementation. To use it, you first need to install the Microsoft.Extensions.Caching.Memory
NuGet package.
Here’s an example of how to use MemoryCache
in a .NET application:
using Microsoft.Extensions.Caching.Memory;
using System;
public class CacheService
{
private readonly IMemoryCache _cache;
public CacheService(IMemoryCache cache)
{
_cache = cache;
}
public string GetCachedData(string key)
{
string data;
if (!_cache.TryGetValue(key, out data))
{
data = GetDataFromExpensiveOperation();
_cache.Set(key, data, new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
});
}
return data;
}
private string GetDataFromExpensiveOperation()
{
// Simulate an expensive operation.
return "Expensive data";
}
}
IDistributedCache
is an interface for distributed cache implementations. Some popular implementations include:
DistributedMemoryCache
(for testing purposes)DistributedRedisCache
(using Redis as the cache store)DistributedSqlServerCache
(using SQL Server as the cache store)To use IDistributedCache
, you will need to install the appropriate NuGet package for the chosen implementation, such as Microsoft.Extensions.Caching.StackExchangeRedis
for Redis.
Here’s an example of how to use IDistributedCache
with Redis in an ASP.NET Core application:
// Startup.cs
using Microsoft.Extensions.Caching.StackExchangeRedis;
public void ConfigureServices(IServiceCollection services)
{
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost";
options.InstanceName = "SampleInstance";
});
services.AddScoped<CacheService>();
}
// CacheService.cs
using Microsoft.Extensions.Caching.Distributed;
using System.Text;
public class CacheService
{
private readonly IDistributedCache _cache;
public CacheService(IDistributedCache cache)
{
_cache = cache;
}
public async Task<string> GetCachedDataAsync(string key)
{
var data = await _cache.GetStringAsync(key);
if (data == null)
{
data = GetDataFromExpensiveOperation();
await _cache.SetStringAsync(key, data, new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
});
}
return data;
}
private string GetDataFromExpensiveOperation()
{
// Simulate an expensive operation.
return "Expensive data";
}
}
Microsoft.Extensions.Caching supports the following cache eviction policies:
Cache entries can also be evicted by a CancellationToken
or by using a PostEvictionCallback
delegate to handle custom eviction scenarios.
Cache tagging and versioning are useful techniques for managing cache dependencies and invalidation. Tags allow you to associate one or more labels with a cached item, making it easier to invalidate multiple items at once. Versioning involves appending a version number to the cache key to ensure that the latest data is being retrieved.
Here’s an example of how to implement cache tagging and versioning with MemoryCache
:
public class CacheService
{
private readonly IMemoryCache _cache;
private const string VersionKey = "CacheVersion";
public CacheService(IMemoryCache cache)
{
_cache = cache;
}
public string GetCachedData(string key, string tag)
{
string versionedKey = GetVersionedKey(key, tag);
string data;
if (!_cache.TryGetValue(versionedKey, out data))
{
data = GetDataFromExpensiveOperation();
_cache.Set(versionedKey, data, new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
});
}
return data;
}
public void InvalidateCacheByTag(string tag)
{
int currentVersion = _cache.GetOrCreate<int>(tag, entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(30);
return 0;
});
_cache.Set(tag, currentVersion + 1, new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(30)
});
}
private string GetVersionedKey(string key, string tag)
{
int version = _cache.Get<int>(tag);
return $"{key}|{tag}|{version}";
}
private string GetDataFromExpensiveOperation()
{
// Simulate an expensive operation.
return "Expensive data";
}
}
In this example, we’ve implemented a method GetVersionedKey
that appends the current version number to the cache key. The InvalidateCacheByTag
method increments the version number, effectively invalidating all cache entries with the specified tag.
Microsoft.Extensions.Caching provides a versatile and extensible solution for caching in .NET applications. With in-memory caching using MemoryCache
, distributed caching using IDistributedCache
, and support for cache eviction policies, tagging, and versioning, it offers a comprehensive set of tools to help developers optimize their applications’ performance and responsiveness.