using AsbCloudDb.Model;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository
{
#nullable enable
///
/// CRUD сервис с кешем в оперативке
///
///
///
public class CrudCacheServiceBase : CrudServiceBase
where TDto : AsbCloudApp.Data.IId
where TEntity : class, IId
{
protected string CacheTag = typeof(TDto).Name;
protected TimeSpan CacheOlescence = TimeSpan.FromMinutes(5);
private readonly IMemoryCache memoryCache;
protected int KeySelector(TEntity entity) => entity.Id;
public CrudCacheServiceBase(IAsbCloudDbContext dbContext, IMemoryCache memoryCache)
: base(dbContext)
{
this.memoryCache = memoryCache;
}
public CrudCacheServiceBase(IAsbCloudDbContext dbContext, IMemoryCache memoryCache, Func, IQueryable> makeQuery)
: base(dbContext, makeQuery)
{
this.memoryCache = memoryCache;
}
///
public override async Task InsertAsync(TDto newItem, CancellationToken token)
{
var result = await base.InsertAsync(newItem, token);
if (result > 0)
DropCache();
return result;
}
///
public override async Task InsertRangeAsync(IEnumerable dtos, CancellationToken token)
{
var result = await base.InsertRangeAsync(dtos, token);
if (result > 0)
DropCache();
return result;
}
///
public override async Task> GetAllAsync(CancellationToken token)
{
var cache = await GetCacheAsync(token);
return cache;
}
///
/// Синхронно получить запись по ИД
///
///
///
public override TDto? GetOrDefault(int id)
{
var cache = GetCache();
return cache.FirstOrDefault(d => d.Id == id);
}
///
public override async Task GetOrDefaultAsync(int id, CancellationToken token)
{
var cache = await GetCacheAsync(token);
return cache.FirstOrDefault(d => d.Id == id);
}
///
public override async Task UpdateAsync(TDto dto, CancellationToken token)
{
var result = await base.UpdateAsync(dto, token);
if (result > 0)
DropCache();
return result;
}
///
public override async Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token)
{
var result = await base.UpdateRangeAsync(dtos, token);
if (result > 0)
DropCache();
return result;
}
///
public override async Task DeleteAsync(int id, CancellationToken token)
{
var result = await base.DeleteAsync(id, token);
if (result > 0)
DropCache();
return result;
}
protected virtual Task> GetCacheAsync(CancellationToken token)
{
var cache = memoryCache.GetOrCreateAsync(CacheTag, async (cacheEntry) => {
cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence;
cacheEntry.SlidingExpiration = CacheOlescence;
var entities = await GetQuery().ToArrayAsync(token);
var dtos = entities.Select(Convert);
return dtos.ToArray().AsEnumerable();
});
return cache;
}
protected virtual IEnumerable GetCache()
{
var cache = memoryCache.GetOrCreate(CacheTag, cacheEntry => {
cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence;
cacheEntry.SlidingExpiration= CacheOlescence;
var entities = GetQuery().ToArray();
var dtos = entities.Select(Convert);
return dtos.ToArray();
});
return cache;
}
protected virtual void DropCache()
=> memoryCache.Remove(CacheTag);
}
#nullable disable
}