当实体更改时,您需要使缓存键无效。
这可能有点棘手,如果你直接在 DbContext 上操作的话。但是由于您使用的是存储库模式,所以这样做更容易。
归结为将IMemoryCache 注入您的存储库并在图片更新时使其失效。
public class PhotographRepository : IPhotograpRepository
{
private readonly IMemoryCache _cache;
public PhotographReposiory(IMemoryCache cache, ...)
{
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
}
public async Task Update(PhotographEntity entity)
{
// update your entity here
await _context.SaveChangesAsync();
// this invalidates your memory cache. Next call to _cache.TryGetValue
// results in a cache miss and the new entity is fetched from the database
_cache.Remove(GetClientCacheKey(entityName, clientId));
}
}
使用装饰模式
public class PhotographRepository : IPhotograpRepository
{
private readonly ApplicationDbContext _context;
public PhotographReposiory(ApplicationDbContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public async Task Update(PhotographEntity entity)
{
// update your entity here
await _context.SaveChangesAsync();
}
}
public class CachedPhotographRepository : IPhotograpRepository
{
private readonly IMemoryCache _cache;
private readonly IPhotograpRepository _repository;
public CachedPhotographRepository(IPhotograpRepository repository, IMemoryCache cache)
{
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_repository = _repository ?? throw new ArgumentNullException(nameof(repository));
}
public async Task Update(PhotographEntity entity)
{
// do the update in the passed in repository
await _repository.Update(entity);
// if no exception is thrown, it was successful
_cache.Remove(GetClientCacheKey(entityName, clientId));
}
}
问题是,内置的 DI/IoC 容器不支持装饰器注册,因此您必须通过工厂模式自己制作或使用支持它的第 3 方 IoC 容器。
services.AddScoped<IPhotograpRepository>(provider =>
// Create an instance of PhotographRepository and inject the memory cache
new CachedPhotographRepository(
// create an instance of the repository and resolve the DbContext and pass to it
new PhotographRepository(provider.GetRequiredService<ApplicationDbContext>()),
provider.GetRequiredService<IMemoryCache>()
)
);
在组合根(配置 DI/IoC 容器的地方)中使用 new 本身并不是“坏事”,但使用第 3 方 IoC 容器更方便。
当然,您也可以在 IoC 容器中注册 PhotographRepository 并解决它。但这也允许您将PhotographRepository 注入到您的服务中,而上面的方法阻止了它,因为只注册了IPhotographRepository 接口。