diff --git a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj
index 1a8e2432..84cf9062 100644
--- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj
+++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj
@@ -43,6 +43,7 @@
+
diff --git a/AsbCloudInfrastructure/Repository/UserRepository.cs b/AsbCloudInfrastructure/Repository/UserRepository.cs
index 9a666b68..0b5a3a58 100644
--- a/AsbCloudInfrastructure/Repository/UserRepository.cs
+++ b/AsbCloudInfrastructure/Repository/UserRepository.cs
@@ -1,9 +1,7 @@
using AsbCloudApp.Data;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
-using AsbCloudDb;
using AsbCloudDb.Model;
-using AsbCloudInfrastructure.EfCache;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
@@ -11,6 +9,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.Extensions.Caching.Memory;
namespace AsbCloudInfrastructure.Repository
{
@@ -29,10 +28,12 @@ namespace AsbCloudInfrastructure.Repository
dst => dst.Files,
dst => dst.RelationUsersUserRoles)
.Config;
-
- public UserRepository(IAsbCloudDbContext dbContext, IUserRoleRepository userRoleRepository) {
+ private readonly IMemoryCache memoryCache;
+ public UserRepository(IAsbCloudDbContext dbContext, IUserRoleRepository userRoleRepository, IMemoryCache memoryCache)
+ {
this.dbContext = dbContext;
this.userRoleRepository = userRoleRepository;
+ this.memoryCache = memoryCache;
}
public async Task InsertAsync(UserExtendedDto dto, CancellationToken token)
@@ -58,12 +59,13 @@ namespace AsbCloudInfrastructure.Repository
public async Task> GetAllAsync(CancellationToken token)
{
- var dtos = (await GetCacheUserAsync(token)).ToList();
+ var dtos = (await GetCacheUserAsync(token)).ToList();
+ var listDtos = dtos.ToList();
if (dtos is null)
return Enumerable.Empty();
- for (var i = 0; i < dtos.Count; i++)
- dtos[i].RoleNames = GetRolesNamesByIdUser(dtos[i].Id);
+ for (var i = 0; i < listDtos.Count; i++)
+ listDtos[i].RoleNames = GetRolesNamesByIdUser(listDtos[i].Id);
return dtos;
}
@@ -170,31 +172,43 @@ namespace AsbCloudInfrastructure.Repository
throw new ArgumentInvalidException($"Login {login} is busy by {existingUserDto.MakeDisplayName()}, id{existingUserDto.Id}", nameof(login));
}
- private Task> GetCacheUserAsync(CancellationToken token)
- => dbContext.Users
+ private async Task> GetCacheUserAsync(CancellationToken token)
+ {
+ var query = dbContext.Users
.Include(r => r.Company)
- .Include(r => r.RelationUsersUserRoles)
- .FromCacheAsync(userCacheTag, cacheObsolence, Convert, token);
+ .Include(r => r.RelationUsersUserRoles);
+ return await FromCacheAsync(query, userCacheTag, cacheObsolence, Convert, token);
+ }
private IEnumerable GetCacheUser()
- => dbContext.Users
+ {
+ var query = dbContext.Users
.Include(r => r.Company)
- .Include(r => r.RelationUsersUserRoles)
- .FromCache(userCacheTag, cacheObsolence, Convert);
+ .Include(r => r.RelationUsersUserRoles);
+ return FromCache(query, userCacheTag, cacheObsolence, Convert);
+ }
private void DropCacheUsers()
- => dbContext.Users.DropCache(userCacheTag);
+ {
+ memoryCache.Remove(userCacheTag);
+ }
- private Task> GetCacheRelationUserUserRoleAsync(CancellationToken token)
- => dbContext.RelationUserUserRoles
+ private async Task> GetCacheRelationUserUserRoleAsync(CancellationToken token)
+ {
+ var query = dbContext.RelationUserUserRoles
.Include(r => r.UserRole)
- .Include(r => r.User)
- .FromCacheAsync(relationUserUserRoleCacheTag, cacheObsolence, token);
+ .Include(r => r.User);
+ return await FromCacheAsync(query, relationUserUserRoleCacheTag, cacheObsolence, token);
+ }
private IEnumerable GetCachRelationUserUserRoleCacheTag()
- => dbContext.RelationUserUserRoles
- .Include(r => r.UserRole)
- .Include(r => r.User)
- .FromCache(relationUserUserRoleCacheTag, cacheObsolence);
+ {
+ var query = dbContext.RelationUserUserRoles
+ .Include(r => r.UserRole)
+ .Include(r => r.User);
+ return FromCache(query, relationUserUserRoleCacheTag, cacheObsolence);
+ }
private void DropCacheRelationUserUserRoleCacheTag()
- => dbContext.RelationUserUserRoles.DropCache(relationUserUserRoleCacheTag);
+ {
+ memoryCache.Remove(relationUserUserRoleCacheTag);
+ }
private async Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable newRoles, CancellationToken token)
{
@@ -212,6 +226,71 @@ namespace AsbCloudInfrastructure.Repository
DropCacheRelationUserUserRoleCacheTag();
}
+ public async Task> FromCacheAsync(IQueryable query, string tag, TimeSpan obsolescence, Func convert, CancellationToken token)
+ where TEntity : class
+ {
+ async Task factory(CancellationToken token)
+ => await query.AsNoTracking().ToArrayAsync(token);
+ var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token);
+ return cache.Select(convert);
+ }
+ public async Task> FromCacheAsync(IQueryable query, string tag, TimeSpan obsolescence, CancellationToken token)
+ where TEntity : class
+ {
+ async Task factory(CancellationToken token)
+ => await query.AsNoTracking().ToArrayAsync(token);
+ var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token);
+ return cache;
+ }
+ public IEnumerable FromCache(IQueryable query, string tag, TimeSpan obsolescence, Func convert)
+ where TEntity : class
+ {
+ TEntity[] factory()
+ => query.AsNoTracking().ToArray();
+ var cache = GetOrAddCache(tag, factory, obsolescence);
+ return cache.Select(convert);
+ }
+ public IEnumerable FromCache(IQueryable query, string tag, TimeSpan obsolescence)
+ where TEntity : class
+ {
+ TEntity[] factory()
+ => query.AsNoTracking().ToArray();
+ var cache = GetOrAddCache(tag, factory, obsolescence);
+ return cache;
+ }
+ private async Task GetOrAddCacheAsync(string tag, Func> valueFactoryAsync, TimeSpan obsolete, CancellationToken token)
+
+ {
+ memoryCache.TryGetValue(tag, out TEntity[]? cached);
+ if (cached == null)
+ {
+ var values = await valueFactoryAsync(token);
+
+ if (values != null)
+ {
+ memoryCache.Set(tag, values, new MemoryCacheEntryOptions().SetAbsoluteExpiration(obsolete));
+ }
+ return values!;
+ }
+ return cached;
+ }
+ private TEntity[] GetOrAddCache(string tag, Func valueFactory, TimeSpan obsolete)
+
+ {
+ memoryCache.TryGetValue(tag, out TEntity[]? cached);
+ if (cached == null)
+ {
+ var values = valueFactory();
+
+ if (values != null)
+ {
+ memoryCache.Set(tag, values, new MemoryCacheEntryOptions().SetAbsoluteExpiration(obsolete));
+ }
+ return values!;
+ }
+ return cached;
+ }
+
protected virtual User Convert(UserExtendedDto dto)
{
var entity = dto.Adapt(userTypeAdapterConfig);