Caching C#IUnitOfWork、IRepository和IMemoryCache[ASP.Net核心]

Caching C#IUnitOfWork、IRepository和IMemoryCache[ASP.Net核心],caching,asp.net-core,repository-pattern,unit-of-work,Caching,Asp.net Core,Repository Pattern,Unit Of Work,我的目标是将我的数据放入缓存。我用它作为我代码的灵感 我的WebApi使用Asp.net内核 GitHub 我在GitHub上创建了一个分支以了解更多详细信息: CacheRepository public class CacheRepository<TEntity, TPrimaryKey> : Repository<TEntity, TPrimaryKey>, ICacheRepository<TEntity, TPrimaryKey> whe

我的目标是将我的数据放入缓存。我用它作为我代码的灵感

我的WebApi使用Asp.net内核

GitHub

我在GitHub上创建了一个分支以了解更多详细信息:

CacheRepository

public class CacheRepository<TEntity, TPrimaryKey> : Repository<TEntity, TPrimaryKey>, ICacheRepository<TEntity, TPrimaryKey>
  where TEntity : class, IEntity<TPrimaryKey>
{
    private readonly IMemoryCache _memoryCache;

    public CacheRepository(DbContext dbContext, IMemoryCache memoryCache)
        : base(dbContext)
    {
        _memoryCache = memoryCache;
    }

    public override TEntity FirstOrDefault(TPrimaryKey id)
    {
        if (!_memoryCache.TryGetValue(GetCacheKey(id), out TEntity result))
        {
            result = base.FirstOrDefault(id);
            if (result != null)
            {
                PutInCache(result);
            }
        }

        return result;
    }

    public override void Delete(Expression<Func<TEntity, bool>> predicate)
    {
        foreach (var entity in GetAll().Where(predicate).ToList())
        {
            Delete(entity);
        }
    }

    public override void Delete(TEntity entity)
    {
        base.Delete(entity);
        RemoveFromCache(entity.Id);
    }

    public override void Delete(TPrimaryKey id)
    {
        base.Delete(id);
        RemoveFromCache(id);
    }

    public override Task DeleteAsync(Expression<Func<TEntity, bool>> predicate)
    {
        return Task.Run(() => Delete(predicate));
    }

    public override Task DeleteAsync(TEntity entity)
    {
        return Task.Run(() => Delete(entity));
    }

    public override Task DeleteAsync(TPrimaryKey id)
    {
        return Task.Run(() => Delete(id));
    }

    public override Task<TEntity> FirstOrDefaultAsync(TPrimaryKey id)
    {
        return _memoryCache.GetOrCreateAsync(
            GetCacheKey(id),
            e => base.FirstOrDefaultAsync(id)
        );
    }

    public override List<TEntity> GetAllList()
    {
        var entities = GetAllEntitiesFromCache();
        if (entities == null)
        {
            entities = base.GetAllList();
            foreach (var entity in entities)
            {
                PutInCache(entity);
            }
        }

        return entities.ToList();
    }

    public override async Task<List<TEntity>> GetAllListAsync()
    {
        var entities = GetAllEntitiesFromCache();
        if (entities == null)
        {
            entities = await base.GetAllListAsync();
            foreach (var entity in entities)
            {
                PutInCache(entity);
            }
        }

        return entities.ToList();
    }

    public override TEntity Get(TPrimaryKey id)
    {
        return _memoryCache.GetOrCreate(
            GetCacheKey(id),
            e => base.Get(id)
        );
    }

    public override Task<TEntity> GetAsync(TPrimaryKey id)
    {
        return _memoryCache.GetOrCreate(
            GetCacheKey(id),
            e => base.GetAsync(id)
        );
    }

    public override TEntity Insert(TEntity entity)
    {
        return PutInCache(base.Insert(entity));
    }

    public override TPrimaryKey InsertAndGetId(TEntity entity)
    {
        return Insert(entity).Id;
    }

    public override Task<TPrimaryKey> InsertAndGetIdAsync(TEntity entity)
    {
        return Task.FromResult(InsertAndGetId(entity));
    }

    public override Task<TEntity> InsertAsync(TEntity entity)
    {
        return Task.FromResult(Insert(entity));
    }

    public override TEntity Update(TEntity entity)
    {
        return UpdateInCache(base.Update(entity));
    }

    public override TEntity Update(TPrimaryKey id, Action<TEntity> updateAction)
    {
        return UpdateInCache(base.Update(id, updateAction));
    }

    public override Task<TEntity> UpdateAsync(TEntity entity)
    {
        return Task.FromResult(Update(entity));
    }

    public override async Task<TEntity> UpdateAsync(TPrimaryKey id, Func<TEntity, Task> updateAction)
    {
        return UpdateInCache(await base.UpdateAsync(id, updateAction));
    }

    #region Private

    private TEntity PutInCache(TEntity entity)
    {
        return _memoryCache.Set(GetCacheKey(entity.Id), entity);
    }

    private void RemoveFromCache(TPrimaryKey id)
    {
        _memoryCache.Remove(GetCacheKey(id));
    }

    private TEntity UpdateInCache(TEntity entity)
    {
        RemoveFromCache(entity.Id);
        return PutInCache(entity);
    }



    private string GetCacheKey(TPrimaryKey id)
    {
        return typeof(TEntity).FullName + id;
    }

    private IList<TEntity> GetAllEntitiesFromCache()
    {
        return _memoryCache.Get<List<TEntity>>(typeof(TEntity));
    }
    #endregion
}
public类CacheRepository:Repository,ICacheRepository
其中tenty:类,tenty
{
私有只读IMemoryCache\u memoryCache;
公共缓存存储库(DbContext DbContext,IMemoryCache memoryCache)
:base(dbContext)
{
_memoryCache=memoryCache;
}
public override TEntity FirstOrDefault(TPrimaryKey id)
{
if(!\u memoryCache.TryGetValue(GetCacheKey(id),输出结果))
{
结果=base.FirstOrDefault(id);
如果(结果!=null)
{
PutInCache(结果);
}
}
返回结果;
}
公共覆盖无效删除(表达式谓词)
{
foreach(GetAll()中的var实体。其中(谓词).ToList())
{
删除(实体);
}
}
公共覆盖无效删除(TEntity实体)
{
基础。删除(实体);
RemoveFromCache(entity.Id);
}
公共覆盖无效删除(TPrimaryKey id)
{
删除(id);
RemoveFromCache(id);
}
公共重写任务DeleteAsync(表达式谓词)
{
返回Task.Run(()=>Delete(谓词));
}
公共覆盖任务DeleteAsync(TEntity实体)
{
返回任务。运行(()=>删除(实体));
}
公共覆盖任务DeleteAsync(TPrimaryKey id)
{
返回任务。运行(()=>Delete(id));
}
公共重写任务FirstOrDefaultAsync(TPrimaryKey id)
{
return\u memoryCache.GetOrCreateAsync(
GetCacheKey(id),
e=>base.FirstOrDefaultAsync(id)
);
}
公共覆盖列表GetAllList()
{
var entities=GetAllentiesFromCache();
如果(实体==null)
{
entities=base.GetAllList();
foreach(实体中的var实体)
{
PutInCache(实体);
}
}
返回实体。ToList();
}
公共重写异步任务GetAllListAsync()
{
var entities=GetAllentiesFromCache();
如果(实体==null)
{
entities=await base.GetAllListAsync();
foreach(实体中的var实体)
{
PutInCache(实体);
}
}
返回实体。ToList();
}
公共覆盖权限获取(TPrimaryKey id)
{
return\u memoryCache.GetOrCreate(
GetCacheKey(id),
e=>base.Get(id)
);
}
公共覆盖任务GetAsync(TPrimaryKey id)
{
return\u memoryCache.GetOrCreate(
GetCacheKey(id),
e=>base.GetAsync(id)
);
}
公共覆盖TEntity插入(TEntity实体)
{
返回PutInCache(base.Insert(entity));
}
公共覆盖TPrimaryKey InsertAndGetId(TEntity实体)
{
返回Insert(entity).Id;
}
公共覆盖任务InsertAndGetIdAsync(TEntity实体)
{
返回Task.FromResult(InsertAndGetId(entity));
}
公共覆盖任务插入同步(TEntity实体)
{
返回Task.FromResult(插入(实体));
}
公共覆盖TEntity更新(TEntity实体)
{
返回UpdateInCache(base.Update(entity));
}
公共覆盖权限更新(TPrimaryKey id,Action updateAction)
{
返回UpdateInCache(base.Update(id,updateAction));
}
公共覆盖任务更新同步(TEntity实体)
{
返回Task.FromResult(更新(实体));
}
公共重写异步任务UpdateAsync(TPrimaryKey id,Func updateAction)
{
返回UpdateInCache(wait base.UpdateAsync(id,updateAction));
}
#地区私人
私有TEntity PutInCache(TEntity实体)
{
返回_memoryCache.Set(GetCacheKey(entity.Id),entity);
}
私有void RemoveFromCache(TPrimaryKey id)
{
_Remove(GetCacheKey(id));
}
私有TEntity UpdateInCache(TEntity实体)
{
RemoveFromCache(entity.Id);
返回PutInCache(实体);
}
私有字符串GetCacheKey(TPrimaryKey id)
{
返回typeof(tenty).FullName+id;
}
私有IList GetAllentiesFromCache()
{
return _memoryCache.Get(typeof(tenty));
}
#端区
}
我的问题:

关于我的CacheRepository,我有很多问题要问,但我不得不减少它,以便能够发布我的文章

=>在UnitOfWork.SubmitChanges之前插入/编辑/删除时,直接在CacheRepository中添加/编辑/删除是件好事吗


如果您对CacheRepository有任何建议或建议,请与我们分享,我真的很想了解更多信息。

通常,在进程尚未完成时从缓存中删除某些内容可能会导致问题。即使在使用orm时,您的dbms也会为您做出这样的决定,因此还不能确定这些更改是否会生效。当您本可以在从给定缓存中删除对象之前等待该过程完成时,您最终将深入挖掘所有异常和readd内容

当我在你的代码中挖掘一点时,我想到的其他事情(非常干净,+1)如下

  • 通用存储库模式是一种新模式。我也喜欢在简单的场景中使用它,但这并不是真的必要
  • 您现在不仅负责缓存,还负责对数据库执行CRUD操作。这是违反法律的
  • 它不仅是一个缓存和一个工作单元,还是一个工厂、一个存储库,以及已经实现的功能之上的另一层。同样,这是违反SRP的
  • 这个。你正在使用