using Microsoft.Extensions.Caching.Distributed; using StackExchange.Redis; namespace yourproject.Cache { public interface IRedisCacheService { Task<T> GetOrSetRedisCacheAsync<T>(string key, Func<Task<T>> fetchData, TimeSpan? expiry = null); Task SetRedisCacheAsync<T>(string key, T data, TimeSpan? expiration = null); Task RemoveRedisCacheAsync(string key); Task RemoveRedisKeysContainingAsync(string basekey, string key); } public class RedisCacheService : IRedisCacheService { private readonly IDistributedCache _redisCache; private readonly ConnectionMultiplexer _redisConnection; public RedisCacheService(IDistributedCache cache, ConnectionMultiplexer redisConnection) { _redisCache = cache; _redisConnection = redisConnection; } public async Task<T> GetOrSetRedisCacheAsync<T>(string key, Func<Task<T>> fetchData, TimeSpan? expiry = null) { var cachedValue = await _redisCache.GetStringAsync(key); if (cachedValue != null) return JsonConvert.DeserializeObject<T>(cachedValue); var data = await fetchData(); await SetRedisCacheAsync(key, data, expiry); return data; } public async Task SetRedisCacheAsync<T>(string key, T data, TimeSpan? expiry = null) { var serializedData = JsonConvert.SerializeObject(data); var cacheOptions = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = expiry ?? TimeSpan.FromMinutes(1440) }; await _redisCache.SetStringAsync(key, serializedData, cacheOptions); } public async Task RemoveRedisCacheAsync(string key) { await _redisCache.RemoveAsync(key); } public async Task RemoveRedisKeysContainingAsync(string basekey, string key) { var server = _redisConnection.GetServer(_redisConnection.GetEndPoints().First()); var keys = server.Keys(pattern: $"*{basekey}*").ToArray(); foreach (var rediskey in keys) { if (rediskey.ToString().Contains(basekey) && rediskey.ToString().Contains(key)) { await _redisCache.RemoveAsync(rediskey.ToString()); } } } } }
Register services in the Program.cs file.
// Register RedisCacheService string redisCacheDbString = Environment.GetEnvironmentVariable("redisConnectionString")!; builder.Services.AddSingleton(sp => { return ConnectionMultiplexer.Connect(redisCacheDbString); }); builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = redisCacheDbString; }); builder.Services.AddSingleton<IRedisCacheService, RedisCacheService>();
Add and Remove cache in Controllers.cs
using yourproject.Cache; using yourproject.Entities; namespace yourproject.Controllers { [ApiController] [Route("api/[controller]")] public class UserController : ControllerBase { private readonly IUserService _serviceProvider; private readonly IRedisCacheService _cachingService; public UserController(IUserService serviceProvider, IRedisCacheService cachingService) { _serviceProvider = serviceProvider; _cachingService = cachingService; } [HttpGet("{id}")] public async Task<IActionResult> Get(int id) { var cacheKey = $"user_{id}"; var response = await _cachingService.GetOrSetRedisCacheAsync( cacheKey, () => _serviceProvider.GetUserByID() ); return response == null ? NotFound() : Ok(response); } [HttpGet("GetAllUser")] public async Task<IActionResult> GetAllUser() { var cacheKey = $"user_getall"; var response = await _cachingService.GetOrSetRedisCacheAsync( cacheKey, () => _serviceProvider.GetAllUser() ); return response == null ? NotFound() : Ok(response); } [HttpPut] public async Task<IActionResult> Edit([FromBody] UserRegisterItemModel user) { var validation = true; // custome logic. like validate user role, etc if (validation) { //Remove specific key await _cachingService.RemoveRedisCacheAsync($"user_{user.ID}"); //Remove multiple keys using contains. await _cachingService.RemoveRedisKeysContainingAsync("user_", user.ID); return Ok(await _serviceProvider.UpdateUser(User)); } else { return BadRequest(); } } } }
Post Comments(0)