.NET 6 Implementing MemoryCache
When the need is performance and you got static data list. You can use in memory cache!
We need to Register MemoryCache
service in Program.cs
before app.Run()
and builder.Build()
.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddMemoryCache(); // here it is
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseMiddleware<HttpContextLogger>();
app.UseAuthorization();
app.MapControllers();
app.Run();
Then after we have done this we can use in memory cache by resolving it from IoC.
I have a default controller (WheatherForecastController.cs). First we will resolve IMemoryCache
at constructor. After that we could be able to Set our items in memory.
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly IMemoryCache _cache;
public WeatherForecastController(IMemoryCache memoryCache) // resolved from DI container
{
_cache = memoryCache;
_cache.Set<string[]>("MyTestKey", new string[] { "ValueOne", "ValueTwo", "ValueThird" });
}
}
Above; Set<T>
expects a value type which is string array and also it needs a key to map these value to the given key. Which is “MyTestKey” in this case;
So we can manage these values by giving key by memoryCache.Get<T>
. Let’s write a api method;
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly IMemoryCache _cache;
public WeatherForecastController(IMemoryCache memoryCache)
{
_cache = memoryCache;
_cache.Set<string[]>("MyTestKey", new string[] { "ValueOne", "ValueTwo", "ValueThird" });
}
[HttpGet(Name = "GetWeatherForecast")]
public string[] Get()
{
return _cache.Get<string[]>("MyTestKey");
}
}
The Get method will return the values of given cache key.
Result of the Get request;
The cache values returned to the requester. We can manage this cache values from every controller that resolves MemoryCache.
We can also give some options by using MemoryCacheEntryOptions
. But first let’s push cache initial values inside another api method. So that initial values won’t be pushed to cache at every api request.
[HttpPost(Name = "PostWeatherForecast")]
public void Post()
{
MemoryCacheEntryOptions options = PrepareOptions();
cache.Set<string[]>("MyTestKey", new string[] { "ValueOne", "ValueTwo", "ValueThird" }, options);
}
Above we have moved the code block inside ctor to this,
The method that generate MemoryCacheEntryOptions
,
public MemoryCacheEntryOptions PrepareOptions()
{
return new MemoryCacheEntryOptions()
{
AbsoluteExpiration = DateTime.Now.AddSeconds(15)
};
}
There is a property called AbsoluteExpiration
. The cache items will be removed after the given time offset. 15 seconds is the expected expiration time for now,
So, Let’s make request to the Post method first, and then call Get method, after 15 seconds. Get Method will return 204 (No content)!
Initial Post request,
Now Let’s look at cache values first,
Okay we got the initial cache items, after 15 seconds, item’s are removed from the cache!
There is also a event that will be triggered when cache expired.
Let’s write the delegate method first,
private void ExpirationCallback(object key, object value, EvictionReason reason, object state)
{
MemoryCacheEntryOptions options = PrepareOptions().RegisterPostEvictionCallback(ExpirationCallback);
_cache.Set<string[]>(key, new string[] { "AfterExpireOne", "AfterExpireTwo", "AfterExpireThird" }, options);
}
Purpose of this method will be; After cache items removed, push another values inside. But these values will expire also. So register calllback in this scope again!
Post method will change like this,
[HttpPost(Name = "PostWeatherForecast")]
public void Post()
{
MemoryCacheEntryOptions options = PrepareOptions().RegisterPostEvictionCallback(ExpirationCallback);;
_cache.Set<string[]>("MyTestKey", new string[] { "ValueOne", "ValueTwo", "ValueThird" }, options);
}
We have registered callback for the initial values.
After 15 seconds, this callback will be triggered;
And after callback executed, we have the new values;
Looks cool!