Asp.net Cache Core – using in memory cache
Most of the apps we write have some data that not get updated frequently or not get updated at all. For example – suburb list, user roles, etc. We can avoid reading the database for all those entities by using a cached collection. if you do have to update the cache you can by using a cache.Remove(‘key’); below is the implementation I used for one of my entities (of course you can write fancier code:) )
public interface IOutletCacheService { void Clear(); Task<IEnumerable<Outlet>> GetOutlets(); }
Here is the simple implementation.
public class OutletCacheService : IOutletCacheService { private const string outletCacheKey = "outlet-cache-key-ha-ha-ha"; private readonly IMemoryCache _cache; private readonly MybContext _db; public TradingOutletCacheService(IMemoryCache cache, MybContext db) { _cache = cache; _db = db; } public void Clear() { _cache.Remove(outletCacheKey); } public async Task<IEnumerable<TradingOutlet>> GetOutlets() { if (_cache.TryGetValue(outletCacheKey , out IEnumerable<Outlet> outlets)) { return outlets; } outlets = await _db.Outlets.Where(o => o.Active == true).ToListAsync(); _cache.Set(outletCacheKey, outlets); return outlets; } }
Easy ?
Now in the Startup.cs, maybe you can register it as a Singleton? I have not tested it out yet.
public void ConfigureServices(IServiceCollection services) { services.AddMediatR(); ...... services.AddMvc(); services.AddMemoryCache(); services.AddAutoMapper(GetType().Assembly); services.AddScoped<IPasswordHasher, PasswordHasher>(); services.AddScoped<IJwtTokenGenerator, JwtTokenGenerator>(); services.AddScoped<ICurrentUserAccessor, CurrentUserAccessor>(); services.AddScoped<IOutletCacheService, OutletCacheService>(); ...... ...... services.AddJwt(); }
Whenever I need to refresh it I call _cacheService.Clear(), like below.
public class Update { public class Handler : IRequestHandler<UpdateCommand, OutletEnvelope> { private readonly MyContext _db; private readonly IOutletCacheService _cacheService; public Handler(MyContext db, IOutletCacheService cacheService) { _db = db; _cacheService = cacheService; } public async Task<OutletEnvelope> Handle(UpdateCommand message, CancellationToken cancellationToken) { var entity = await _db.Outlets .Where(o => o.OutletId == message.OutletId) .SingleOrDefaultAsync(cancellationToken); if (entity == null) throw new RestException(HttpStatusCode.NotFound); Mapper.Map(message, entity); await _db.SaveChangesAsync(cancellationToken); _cacheService.Clear(); return new OutletEnvelope(entity); } }
Happy coding