gpt4 book ai didi

c# - 实体更改后更新 IMemoryCache

转载 作者:行者123 更新时间:2023-12-04 12:06:50 25 4
gpt4 key购买 nike

我有一个 CacheService使用 GetOrCreateAsync基于键创建缓存。我正在缓存一个照片实体,它有一个 byte[]属性(property)。
这可以很好地缓存并按预期检索。但是,如果照片实体已更新,缓存仍会像您预期的那样保留旧实体,因为它尚未过期,如何在保存此实体时强制更新缓存?我是否删除现有的缓存实体并重新添加更新的实体?

我的 FromCacheAsync 的例子我的方法 CacheService

    public async Task<T> FromCacheAsync<T>(string entityName, int clientId, Func<Task<T>> function)
{
string cacheKey = GetClientCacheKey(entityName, clientId, function);

if (!_cache.TryGetValue(cacheKey, out T entry))
{
async Task<T> factory(ICacheEntry cacheEntry)
{
return await function();
}
return await _cache.GetOrCreateAsync(cacheKey, factory);
}

return entry;
}

这是使用缓存的示例。
      var existingPhotograph = await _cacheService.FromCacheAsync(nameof(_context.Photograph), clientId, async () =>
await _photographRepository.GetByStaffIdAsync(staff.StaffId));

最佳答案

当实体更改时,您需要使缓存键无效。

如果直接对 DbContext 进行操作,那可能有点棘手。但是由于您使用的是存储库模式,所以更容易做到。

归结为注入(inject)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 容器不支持装饰器注册,因此您必须通过工厂模式自己制作或使用支持它的 3rd 方 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 本身并不“坏”,但是使用 3rd 方 IoC 容器更方便。

当然你也可以注册 PhotographRepository使用 IoC 容器并解决它。但这也将允许您注入(inject) PhotographRepository进入您的服务,而上述阻止它,因为只有 IPhotographRepository接口(interface)已注册。

关于c# - 实体更改后更新 IMemoryCache,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48743516/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com