#8101318 Изменение работы кэша

This commit is contained in:
ai.astrakhantsev 2022-12-01 15:56:11 +05:00
parent 2963d74f43
commit fb5483299d
39 changed files with 298 additions and 252 deletions

View File

@ -29,7 +29,7 @@ namespace AsbCloudApp.Data
/// <summary> /// <summary>
/// Включенные роли /// Включенные роли
/// </summary> /// </summary>
public virtual ICollection<UserRoleDto> Roles { get; set; } public virtual IEnumerable<UserRoleDto> Roles { get; set; }
/// <summary> /// <summary>
/// Пользователи в роли /// Пользователи в роли

View File

@ -11,7 +11,7 @@ namespace AsbCloudApp.Repositories
/// <summary> /// <summary>
/// Сервис доступа к файлам /// Сервис доступа к файлам
/// </summary> /// </summary>
public interface IFileRepository : ICrudService<FileInfoDto> public interface IFileRepository : ICrudRepository<FileInfoDto>
{ {
/// <summary> /// <summary>
/// Получение файлов по скважине /// Получение файлов по скважине

View File

@ -7,7 +7,7 @@ namespace AsbCloudApp.Repositories
/// <summary> /// <summary>
/// Репозиторий пользователей /// Репозиторий пользователей
/// </summary> /// </summary>
public interface IUserRepository : ICrudService<UserExtendedDto> public interface IUserRepository : ICrudRepository<UserExtendedDto>
{ {
/// <summary> /// <summary>
/// Получить список всех прав пользователя (включая наследование групп) /// Получить список всех прав пользователя (включая наследование групп)

View File

@ -10,7 +10,7 @@ namespace AsbCloudApp.Repositories
/// <summary> /// <summary>
/// Разрешения на доступ к данным /// Разрешения на доступ к данным
/// </summary> /// </summary>
public interface IUserRoleRepository : ICrudService<UserRoleDto> public interface IUserRoleRepository : ICrudRepository<UserRoleDto>
{ {
/// <summary> /// <summary>
/// получить dto по названиям /// получить dto по названиям

View File

@ -10,7 +10,7 @@ namespace AsbCloudApp.Services
/// Сервис получения, добавления, изменения, удаления данных /// Сервис получения, добавления, изменения, удаления данных
/// </summary> /// </summary>
/// <typeparam name="TDto"></typeparam> /// <typeparam name="TDto"></typeparam>
public interface ICrudService<TDto> public interface ICrudRepository<TDto>
where TDto : Data.IId where TDto : Data.IId
{ {
/// <summary> /// <summary>

View File

@ -8,7 +8,7 @@ namespace AsbCloudApp.Services
/// <summary> /// <summary>
/// The параметры бурения service. /// The параметры бурения service.
/// </summary> /// </summary>
public interface IDrillParamsService : ICrudService<DrillParamsDto> public interface IDrillParamsService : ICrudRepository<DrillParamsDto>
{ {
/// <summary> /// <summary>
/// default параметры бурения /// default параметры бурения

View File

@ -11,7 +11,7 @@ namespace AsbCloudApp.Services
/// Для сущностей относящихся к скважине /// Для сущностей относящихся к скважине
/// </summary> /// </summary>
/// <typeparam name="Tdto"></typeparam> /// <typeparam name="Tdto"></typeparam>
public interface IRepositoryWellRelated<Tdto> : ICrudService<Tdto> public interface IRepositoryWellRelated<Tdto> : ICrudRepository<Tdto>
where Tdto : IId, IWellRelated where Tdto : IId, IWellRelated
{ {
/// <summary> /// <summary>

View File

@ -9,7 +9,7 @@ namespace AsbCloudApp.Services
/// <summary> /// <summary>
/// сервис скважин /// сервис скважин
/// </summary> /// </summary>
public interface IWellService : ICrudService<WellDto> public interface IWellService : ICrudRepository<WellDto>
{ {
/// <summary> /// <summary>
/// сервис телеметрии /// сервис телеметрии

View File

@ -139,33 +139,33 @@ namespace AsbCloudInfrastructure
services.AddTransient<ILimitingParameterService, LimitingParameterService>(); services.AddTransient<ILimitingParameterService, LimitingParameterService>();
// admin crud services: // admin crud services:
services.AddTransient<ICrudService<TelemetryDto>, CrudServiceBase<TelemetryDto, Telemetry>>(s => services.AddTransient<ICrudRepository<TelemetryDto>, CrudCacheRepositoryBase<TelemetryDto, Telemetry>>(s =>
new CrudCacheServiceBase<TelemetryDto, Telemetry>( new CrudCacheRepositoryBase<TelemetryDto, Telemetry>(
s.GetService<IAsbCloudDbContext>(), s.GetService<IAsbCloudDbContext>(),
s.GetService<IMemoryCache>(), s.GetService<IMemoryCache>(),
dbSet => dbSet.Include(t => t.Well))); // может быть включен в сервис TelemetryService dbSet => dbSet.Include(t => t.Well))); // может быть включен в сервис TelemetryService
services.AddTransient<ICrudService<DrillParamsDto>, DrillParamsService>(); services.AddTransient<ICrudRepository<DrillParamsDto>, DrillParamsService>();
services.AddTransient<ICrudService<DepositDto>, CrudCacheServiceBase<DepositDto, Deposit>>(s => services.AddTransient<ICrudRepository<DepositDto>, CrudCacheRepositoryBase<DepositDto, Deposit>>(s =>
new CrudCacheServiceBase<DepositDto, Deposit>( new CrudCacheRepositoryBase<DepositDto, Deposit>(
s.GetService<IAsbCloudDbContext>(), s.GetService<IAsbCloudDbContext>(),
s.GetService<IMemoryCache>(), s.GetService<IMemoryCache>(),
dbSet => dbSet.Include(d => d.Clusters))); dbSet => dbSet.Include(d => d.Clusters)));
services.AddTransient<ICrudService<CompanyDto>, CrudCacheServiceBase<CompanyDto, Company>>(s => services.AddTransient<ICrudRepository<CompanyDto>, CrudCacheRepositoryBase<CompanyDto, Company>>(s =>
new CrudCacheServiceBase<CompanyDto, Company>( new CrudCacheRepositoryBase<CompanyDto, Company>(
s.GetService<IAsbCloudDbContext>(), s.GetService<IAsbCloudDbContext>(),
s.GetService<IMemoryCache>(), s.GetService<IMemoryCache>(),
dbSet => dbSet.Include(c => c.CompanyType))); dbSet => dbSet.Include(c => c.CompanyType)));
services.AddTransient<ICrudService<CompanyTypeDto>, CrudCacheServiceBase<CompanyTypeDto, CompanyType>>(); services.AddTransient<ICrudRepository<CompanyTypeDto>, CrudCacheRepositoryBase<CompanyTypeDto, CompanyType>>();
services.AddTransient<ICrudService<ClusterDto>, CrudCacheServiceBase<ClusterDto, Cluster>>(s => services.AddTransient<ICrudRepository<ClusterDto>, CrudCacheRepositoryBase<ClusterDto, Cluster>>(s =>
new CrudCacheServiceBase<ClusterDto, Cluster>( new CrudCacheRepositoryBase<ClusterDto, Cluster>(
s.GetService<IAsbCloudDbContext>(), s.GetService<IAsbCloudDbContext>(),
s.GetService<IMemoryCache>(), s.GetService<IMemoryCache>(),
dbSet => dbSet dbSet => dbSet
.Include(c => c.Wells) .Include(c => c.Wells)
.Include(c => c.Deposit))); // может быть включен в сервис ClusterService .Include(c => c.Deposit))); // может быть включен в сервис ClusterService
services.AddTransient<ICrudService<DrillerDto>, CrudCacheServiceBase<DrillerDto, Driller>>(); services.AddTransient<ICrudRepository<DrillerDto>, CrudCacheRepositoryBase<DrillerDto, Driller>>();
services.AddTransient<IFileRepository, FileRepository>(); services.AddTransient<IFileRepository, FileRepository>();
services.AddTransient<IFileStorageRepository, FileStorageRepository>(); services.AddTransient<IFileStorageRepository, FileStorageRepository>();
@ -174,10 +174,10 @@ namespace AsbCloudInfrastructure
services.AddTransient<IUserRepository, UserRepository>(); services.AddTransient<IUserRepository, UserRepository>();
services.AddTransient<ILimitingParameterRepository, LimitingParameterRepository>(); services.AddTransient<ILimitingParameterRepository, LimitingParameterRepository>();
// Subsystem service // Subsystem service
services.AddTransient<ICrudService<SubsystemDto>, CrudCacheServiceBase<SubsystemDto, Subsystem>>(); services.AddTransient<ICrudRepository<SubsystemDto>, CrudCacheRepositoryBase<SubsystemDto, Subsystem>>();
services.AddTransient<ISubsystemService, SubsystemService>(); services.AddTransient<ISubsystemService, SubsystemService>();
services.AddTransient<ICrudService<PermissionDto>, CrudCacheServiceBase<PermissionDto, Permission>>(); services.AddTransient<ICrudRepository<PermissionDto>, CrudCacheRepositoryBase<PermissionDto, Permission>>();
// TelemetryData services // TelemetryData services
services.AddTransient<ITelemetryDataService<TelemetryDataSaubDto>, TelemetryDataSaubService>(); services.AddTransient<ITelemetryDataService<TelemetryDataSaubDto>, TelemetryDataSaubService>();

View File

@ -0,0 +1,70 @@
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
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
{
public class CacheBase<TDto, TEntity> : QueryContainer<TEntity>
where TDto : AsbCloudApp.Data.IId
where TEntity : class, AsbCloudDb.Model.IId
{
protected readonly IMemoryCache memoryCache;
protected string CacheTag = typeof(TDto).Name;
protected TimeSpan CacheOlescence = TimeSpan.FromMinutes(5);
public CacheBase(IAsbCloudDbContext context, IMemoryCache memoryCache)
: base(context)
{
this.memoryCache = memoryCache;
}
public CacheBase(IAsbCloudDbContext context, IMemoryCache memoryCache, Func<DbSet<TEntity>, IQueryable<TEntity>> makeQuery)
: base(context, makeQuery)
{
this.memoryCache = memoryCache;
}
protected virtual void DropCache()
=> memoryCache.Remove(CacheTag);
protected virtual IEnumerable<TDto> GetCache()
{
var cache = memoryCache.GetOrCreate(CacheTag, cacheEntry =>
{
cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence;
cacheEntry.SlidingExpiration = CacheOlescence;
var entities = this.GetQuery().ToArray();
var dtos = entities.Select(Convert);
return dtos.ToArray();
});
return cache;
}
protected virtual Task<IEnumerable<TDto>> GetCacheAsync(CancellationToken token)
{
var cache = memoryCache.GetOrCreateAsync(CacheTag, async (cacheEntry) =>
{
cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence;
cacheEntry.SlidingExpiration = CacheOlescence;
var entities = await this.GetQuery().ToArrayAsync(token);
var dtos = entities.Select(Convert);
return dtos.ToArray().AsEnumerable();
});
return cache;
}
protected virtual TDto Convert(TEntity src) => src.Adapt<TDto>();
protected virtual TEntity Convert(TDto src) => src.Adapt<TEntity>();
}
}

View File

@ -0,0 +1,100 @@
using AsbCloudApp.Services;
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
/// <summary>
/// CRUD ñåðâèñ ñ êåøåì â îïåðàòèâêå
/// </summary>
/// <typeparam name="TDto"></typeparam>
/// <typeparam name="TEntity"></typeparam>
public class CrudCacheRepositoryBase<TDto, TEntity> : CacheBase<TDto, TEntity>, ICrudRepository<TDto>
where TDto : AsbCloudApp.Data.IId
where TEntity : class, IId
{
protected int KeySelector(TEntity entity) => entity.Id;
protected readonly ICrudRepository<TDto> crudServiceBase;
public CrudCacheRepositoryBase(IAsbCloudDbContext dbContext, IMemoryCache memoryCache)
: base(dbContext, memoryCache)
{
crudServiceBase = new CrudRepositoryBase<TDto, TEntity>(dbContext);
}
public CrudCacheRepositoryBase(IAsbCloudDbContext dbContext, IMemoryCache memoryCache, Func<DbSet<TEntity>, IQueryable<TEntity>> makeQuery)
: base(dbContext, memoryCache, makeQuery)
{
crudServiceBase = new CrudRepositoryBase<TDto, TEntity>(dbContext, makeQuery);
}
/// <inheritdoc/>
public async Task<int> InsertAsync(TDto newItem, CancellationToken token)
{
var result = await crudServiceBase.InsertAsync(newItem, token);
if (result > 0)
DropCache();
return result;
}
/// <inheritdoc/>
public async Task<int> InsertRangeAsync(IEnumerable<TDto> dtos, CancellationToken token)
{
var result = await crudServiceBase.InsertRangeAsync(dtos, token);
if (result > 0)
DropCache();
return result;
}
/// <inheritdoc/>
public async Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token)
{
var cache = await GetCacheAsync(token);
return cache;
}
/// <summary>
/// Ñèíõðîííî ïîëó÷èòü çàïèñü ïî ÈÄ
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public TDto? GetOrDefault(int id)
{
var cache = GetCache();
return cache.FirstOrDefault(d => d.Id == id);
}
/// <inheritdoc/>
public async Task<TDto?> GetOrDefaultAsync(int id, CancellationToken token)
{
var cache = await GetCacheAsync(token);
return cache.FirstOrDefault(d => d.Id == id);
}
/// <inheritdoc/>
public async Task<int> UpdateAsync(TDto dto, CancellationToken token)
{
var result = await crudServiceBase.UpdateAsync(dto, token);
if (result > 0)
DropCache();
return result;
}
/// <inheritdoc/>
public async Task<int> DeleteAsync(int id, CancellationToken token)
{
var result = await crudServiceBase.DeleteAsync(id, token);
if (result > 0)
DropCache();
return result;
}
}
#nullable disable
}

View File

@ -1,140 +0,0 @@
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
/// <summary>
/// CRUD ñåðâèñ ñ êåøåì â îïåðàòèâêå
/// </summary>
/// <typeparam name="TDto"></typeparam>
/// <typeparam name="TEntity"></typeparam>
public class CrudCacheServiceBase<TDto, TEntity> : CrudServiceBase<TDto, TEntity>
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<DbSet<TEntity>, IQueryable<TEntity>> makeQuery)
: base(dbContext, makeQuery)
{
this.memoryCache = memoryCache;
}
/// <inheritdoc/>
public override async Task<int> InsertAsync(TDto newItem, CancellationToken token)
{
var result = await base.InsertAsync(newItem, token);
if (result > 0)
DropCache();
return result;
}
/// <inheritdoc/>
public override async Task<int> InsertRangeAsync(IEnumerable<TDto> dtos, CancellationToken token)
{
var result = await base.InsertRangeAsync(dtos, token);
if (result > 0)
DropCache();
return result;
}
/// <inheritdoc/>
public override async Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token)
{
var cache = await GetCacheAsync(token);
return cache;
}
/// <summary>
/// Ñèíõðîííî ïîëó÷èòü çàïèñü ïî ÈÄ
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public override TDto? GetOrDefault(int id)
{
var cache = GetCache();
return cache.FirstOrDefault(d => d.Id == id);
}
/// <inheritdoc/>
public override async Task<TDto?> GetOrDefaultAsync(int id, CancellationToken token)
{
var cache = await GetCacheAsync(token);
return cache.FirstOrDefault(d => d.Id == id);
}
/// <inheritdoc/>
public override async Task<int> UpdateAsync(TDto dto, CancellationToken token)
{
var result = await base.UpdateAsync(dto, token);
if (result > 0)
DropCache();
return result;
}
/// <inheritdoc/>
public override async Task<int> UpdateRangeAsync(IEnumerable<TDto> dtos, CancellationToken token)
{
var result = await base.UpdateRangeAsync(dtos, token);
if (result > 0)
DropCache();
return result;
}
/// <inheritdoc/>
public override async Task<int> DeleteAsync(int id, CancellationToken token)
{
var result = await base.DeleteAsync(id, token);
if (result > 0)
DropCache();
return result;
}
protected virtual Task<IEnumerable<TDto>> 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<TDto> 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
}

View File

@ -16,33 +16,22 @@ namespace AsbCloudInfrastructure.Repository
/// </summary> /// </summary>
/// <typeparam name="TDto"></typeparam> /// <typeparam name="TDto"></typeparam>
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
public class CrudServiceBase<TDto, TEntity> : ICrudService<TDto> public class CrudRepositoryBase<TDto, TEntity> : QueryContainer<TEntity>, ICrudRepository<TDto>
where TDto : AsbCloudApp.Data.IId where TDto : AsbCloudApp.Data.IId
where TEntity : class, IId where TEntity : class, IId
{ {
protected readonly IAsbCloudDbContext dbContext; public CrudRepositoryBase(IAsbCloudDbContext context)
protected readonly DbSet<TEntity> dbSet; : base(context)
protected readonly Func<IQueryable<TEntity>> GetQuery; { }
public CrudServiceBase(IAsbCloudDbContext context) public CrudRepositoryBase(IAsbCloudDbContext context, Func<DbSet<TEntity>, IQueryable<TEntity>> makeQuery)
{ : base(context, makeQuery)
dbContext = context; { }
dbSet = context.Set<TEntity>();
GetQuery = () => dbSet;
}
public CrudServiceBase(IAsbCloudDbContext context, Func<DbSet<TEntity>, IQueryable<TEntity>> makeQuery)
{
dbContext = context;
dbSet = context.Set<TEntity>();
GetQuery = () => makeQuery(dbSet);
}
/// <inheritdoc/> /// <inheritdoc/>
public virtual async Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token = default) public virtual async Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token = default)
{ {
var entities = await GetQuery() var entities = await GetQuery()
//.OrderBy(e => e.Id)
.AsNoTracking() .AsNoTracking()
.ToListAsync(token) .ToListAsync(token)
.ConfigureAwait(false); .ConfigureAwait(false);
@ -117,7 +106,7 @@ namespace AsbCloudInfrastructure.Repository
.ConfigureAwait(false); .ConfigureAwait(false);
if (existingEntity is null) if (existingEntity is null)
return ICrudService<TDto>.ErrorIdNotFound; return ICrudRepository<TDto>.ErrorIdNotFound;
var entity = Convert(item); var entity = Convert(item);
var entry = dbSet.Update(entity); var entry = dbSet.Update(entity);
@ -126,29 +115,6 @@ namespace AsbCloudInfrastructure.Repository
return entry.Entity.Id; return entry.Entity.Id;
} }
public virtual async Task<int> UpdateRangeAsync(IEnumerable<TDto> dtos, CancellationToken token)
{
var ids = dtos.Select(d => d.Id);
var existingEntities = await dbSet
.AsNoTracking()
.Where(d => ids.Contains(d.Id))
.Select(d => d.Id)
.ToListAsync(token)
.ConfigureAwait(false);
if (ids.Count() > existingEntities.Count)
return ICrudService<TDto>.ErrorIdNotFound;
foreach (var dto in dtos)
{
var entity = Convert(dto);
var entry = dbSet.Update(entity);
}
var affected = await dbContext.SaveChangesAsync(token);
return affected;
}
/// <inheritdoc/> /// <inheritdoc/>
public virtual Task<int> DeleteAsync(int id, CancellationToken token = default) public virtual Task<int> DeleteAsync(int id, CancellationToken token = default)
{ {
@ -156,7 +122,7 @@ namespace AsbCloudInfrastructure.Repository
.AsNoTracking() .AsNoTracking()
.FirstOrDefault(e => e.Id == id); .FirstOrDefault(e => e.Id == id);
if (entity == default) if (entity == default)
return Task.FromResult(ICrudService<TDto>.ErrorIdNotFound); return Task.FromResult(ICrudRepository<TDto>.ErrorIdNotFound);
var entry = dbSet.Remove(entity); var entry = dbSet.Remove(entity);
var affected = dbContext.SaveChangesAsync(token); var affected = dbContext.SaveChangesAsync(token);
entry.State = EntityState.Detached; entry.State = EntityState.Detached;

View File

@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository namespace AsbCloudInfrastructure.Repository
{ {
#nullable enable #nullable enable
public class CrudWellRelatedCacheServiceBase<TDto, TEntity> : CrudCacheServiceBase<TDto, TEntity>, IRepositoryWellRelated<TDto> public class CrudWellRelatedCacheServiceBase<TDto, TEntity> : CrudCacheRepositoryBase<TDto, TEntity>, IRepositoryWellRelated<TDto>
where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated
where TEntity : class, IId, IWellRelated where TEntity : class, IId, IWellRelated
{ {

View File

@ -10,7 +10,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository namespace AsbCloudInfrastructure.Repository
{ {
#nullable enable #nullable enable
public class CrudWellRelatedServiceBase<TDto, TEntity> : CrudServiceBase<TDto, TEntity>, IRepositoryWellRelated<TDto> public class CrudWellRelatedServiceBase<TDto, TEntity> : CrudRepositoryBase<TDto, TEntity>, IRepositoryWellRelated<TDto>
where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated
where TEntity : class, IId, IWellRelated where TEntity : class, IId, IWellRelated
{ {

View File

@ -1,15 +1,10 @@
using AsbCloudApp.Data; using AsbCloudApp.Data;
using AsbCloudApp.Repositories; using AsbCloudApp.Repositories;
using AsbCloudApp.Requests; using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb; using AsbCloudDb;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services;
using DocumentFormat.OpenXml.Drawing.Charts;
using DocumentFormat.OpenXml.Wordprocessing;
using Mapster; using Mapster;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Org.BouncyCastle.Asn1.Ocsp;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -0,0 +1,28 @@
using AsbCloudDb.Model;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
namespace AsbCloudInfrastructure.Repository
{
public class QueryContainer<TEntity> where TEntity : class, IId
{
protected readonly IAsbCloudDbContext dbContext;
protected readonly DbSet<TEntity> dbSet;
protected readonly Func<IQueryable<TEntity>> GetQuery;
public QueryContainer(IAsbCloudDbContext context)
{
dbContext = context;
dbSet = context.Set<TEntity>();
GetQuery = () => dbSet;
}
public QueryContainer(IAsbCloudDbContext context, Func<DbSet<TEntity>, IQueryable<TEntity>> makeQuery)
{
dbContext = context;
dbSet = context.Set<TEntity>();
GetQuery = () => makeQuery(dbSet);
}
}
}

View File

@ -4,6 +4,10 @@ using AsbCloudDb.Model;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using System; using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using System.Linq;
namespace AsbCloudInfrastructure.Repository namespace AsbCloudInfrastructure.Repository
{ {
@ -18,6 +22,29 @@ namespace AsbCloudInfrastructure.Repository
this.wellService = wellService; this.wellService = wellService;
} }
public virtual async Task<int> UpdateRangeAsync(IEnumerable<SetpointsRequestDto> dtos, CancellationToken token)
{
var ids = dtos.Select(d => d.Id);
var existingEntities = await dbSet
.AsNoTracking()
.Where(d => ids.Contains(d.Id))
.Select(d => d.Id)
.ToListAsync(token)
.ConfigureAwait(false);
if (ids.Count() > existingEntities.Count)
return ICrudRepository<SetpointsRequestDto>.ErrorIdNotFound;
foreach (var dto in dtos)
{
var entity = Convert(dto);
var entry = dbSet.Update(entity);
}
var affected = await dbContext.SaveChangesAsync(token);
return affected;
}
protected override SetpointsRequestDto Convert(SetpointsRequest src) protected override SetpointsRequestDto Convert(SetpointsRequest src)
{ {
var result = base.Convert(src); var result = base.Convert(src);

View File

@ -12,7 +12,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services namespace AsbCloudInfrastructure.Services
{ {
#nullable enable #nullable enable
public class DrillParamsService : CrudServiceBase<DrillParamsDto, DrillParams>, IDrillParamsService public class DrillParamsService : CrudRepositoryBase<DrillParamsDto, DrillParams>, IDrillParamsService
{ {
private readonly IAsbCloudDbContext db; private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService; private readonly ITelemetryService telemetryService;

View File

@ -10,7 +10,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services namespace AsbCloudInfrastructure.Services
{ {
public class FileCategoryService : CrudCacheServiceBase<FileCategoryDto, FileCategory>, IFileCategoryService public class FileCategoryService : CrudCacheRepositoryBase<FileCategoryDto, FileCategory>, IFileCategoryService
{ {
public FileCategoryService(IAsbCloudDbContext context, IMemoryCache memoryCache) public FileCategoryService(IAsbCloudDbContext context, IMemoryCache memoryCache)
: base(context, memoryCache) { } : base(context, memoryCache) { }

View File

@ -23,13 +23,13 @@ namespace AsbCloudInfrastructure.Services.Subsystems
private readonly IAsbCloudDbContext db; private readonly IAsbCloudDbContext db;
private readonly IWellService wellService; private readonly IWellService wellService;
private readonly ICrudService<SubsystemDto> subsystemService; private readonly ICrudRepository<SubsystemDto> subsystemService;
private readonly IDetectedOperationService detectedOperationService; private readonly IDetectedOperationService detectedOperationService;
public const int IdSubsystemAKB = 1; public const int IdSubsystemAKB = 1;
public const int IdSubsystemMSE = 2; public const int IdSubsystemMSE = 2;
public const int IdSubsystemSpin = 65536; public const int IdSubsystemSpin = 65536;
public const int IdSubsystemTorque = 65537; public const int IdSubsystemTorque = 65537;
public SubsystemOperationTimeService(IAsbCloudDbContext db, IWellService wellService, ICrudService<SubsystemDto> subsystemService, IDetectedOperationService detectedOperationService) public SubsystemOperationTimeService(IAsbCloudDbContext db, IWellService wellService, ICrudRepository<SubsystemDto> subsystemService, IDetectedOperationService detectedOperationService)
{ {
this.db = db; this.db = db;
this.wellService = wellService; this.wellService = wellService;

View File

@ -15,7 +15,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.Subsystems namespace AsbCloudInfrastructure.Services.Subsystems
{ {
#nullable enable #nullable enable
internal class SubsystemService : CrudCacheServiceBase<SubsystemDto, Subsystem>, ISubsystemService internal class SubsystemService : CrudCacheRepositoryBase<SubsystemDto, Subsystem>, ISubsystemService
{ {
private readonly IWellService wellService; private readonly IWellService wellService;
public SubsystemService(IAsbCloudDbContext dbContext, IMemoryCache memoryCache, IWellService wellService) : base(dbContext, memoryCache) public SubsystemService(IAsbCloudDbContext dbContext, IMemoryCache memoryCache, IWellService wellService) : base(dbContext, memoryCache)

View File

@ -15,13 +15,13 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services namespace AsbCloudInfrastructure.Services
{ {
public class WellService : CrudCacheServiceBase<WellDto, Well>, IWellService public class WellService : CrudCacheRepositoryBase<WellDto, Well>, IWellService
{ {
private const string relationCompaniesWellsCacheTag = "RelationCompaniesWells"; private const string relationCompaniesWellsCacheTag = "RelationCompaniesWells";
private static readonly TimeSpan relationCompaniesWellsCacheObsolence = TimeSpan.FromMinutes(15); private static readonly TimeSpan relationCompaniesWellsCacheObsolence = TimeSpan.FromMinutes(15);
private readonly ITelemetryService telemetryService; private readonly ITelemetryService telemetryService;
private readonly ICrudService<CompanyTypeDto> companyTypesService; private readonly ICrudRepository<CompanyTypeDto> companyTypesService;
private readonly ITimezoneService timezoneService; private readonly ITimezoneService timezoneService;
private readonly IWellOperationService wellOperationService; private readonly IWellOperationService wellOperationService;
@ -43,7 +43,7 @@ namespace AsbCloudInfrastructure.Services
this.timezoneService = timezoneService; this.timezoneService = timezoneService;
this.wellOperationService = new WellOperationService.WellOperationService(db, memoryCache, this); this.wellOperationService = new WellOperationService.WellOperationService(db, memoryCache, this);
companyTypesService = new CrudCacheServiceBase<CompanyTypeDto, CompanyType>(dbContext, memoryCache); companyTypesService = new CrudCacheRepositoryBase<CompanyTypeDto, CompanyType>(dbContext, memoryCache);
} }
private IEnumerable<RelationCompanyWell> GetCacheRelationCompanyWell() private IEnumerable<RelationCompanyWell> GetCacheRelationCompanyWell()
@ -86,7 +86,7 @@ namespace AsbCloudInfrastructure.Services
return wellsDtos.ToList(); return wellsDtos.ToList();
} }
public override async Task<int> InsertAsync(WellDto dto, CancellationToken token = default) public async Task<int> InsertAsync(WellDto dto, CancellationToken token = default)
{ {
if (dto.IdWellType is < 1 or > 2) if (dto.IdWellType is < 1 or > 2)
throw new ArgumentInvalidException("Тип скважины указан неправильно.", nameof(dto)); throw new ArgumentInvalidException("Тип скважины указан неправильно.", nameof(dto));
@ -112,12 +112,12 @@ namespace AsbCloudInfrastructure.Services
return result; return result;
} }
public override Task<int> InsertRangeAsync(IEnumerable<WellDto> dtos, CancellationToken token) public Task<int> InsertRangeAsync(IEnumerable<WellDto> dtos, CancellationToken token)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override async Task<int> UpdateAsync(WellDto dto, public async Task<int> UpdateAsync(WellDto dto,
CancellationToken token = default) CancellationToken token = default)
{ {
if (dto.IdWellType is < 1 or > 2) if (dto.IdWellType is < 1 or > 2)

View File

@ -11,7 +11,7 @@ namespace AsbCloudWebApi.Tests
{ {
public static Mock<TRepository> Make<TRepository, TDto>(ICollection<TDto> data) public static Mock<TRepository> Make<TRepository, TDto>(ICollection<TDto> data)
where TDto : AsbCloudApp.Data.IId where TDto : AsbCloudApp.Data.IId
where TRepository : class, ICrudService<TDto> where TRepository : class, ICrudRepository<TDto>
{ {
var repositoryMock = new Mock<TRepository>(); var repositoryMock = new Mock<TRepository>();

View File

@ -9,7 +9,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
public abstract class CrudServiceTestAbstract<TDto> public abstract class CrudServiceTestAbstract<TDto>
where TDto : AsbCloudApp.Data.IId where TDto : AsbCloudApp.Data.IId
{ {
private readonly ICrudService<TDto> service; private readonly ICrudRepository<TDto> service;
public CrudServiceTestAbstract() public CrudServiceTestAbstract()
{ {
@ -17,7 +17,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
service = MakeService(); service = MakeService();
} }
protected abstract ICrudService<TDto> MakeService(); protected abstract ICrudRepository<TDto> MakeService();
protected abstract TDto MakeNewItem(); protected abstract TDto MakeNewItem();
[Fact] [Fact]

View File

@ -19,10 +19,10 @@ namespace AsbCloudWebApi.Tests.ServicesTests
return item; return item;
} }
protected override ICrudService<DepositDto> MakeService() protected override ICrudRepository<DepositDto> MakeService()
{ {
var dbContext = TestHelpter.MakeRealTestContext(); var dbContext = TestHelpter.MakeRealTestContext();
return new CrudCacheServiceBase<DepositDto, Deposit>(dbContext, TestHelpter.MemoryCache); return new CrudCacheRepositoryBase<DepositDto, Deposit>(dbContext, TestHelpter.MemoryCache);
} }
} }
} }

View File

@ -27,11 +27,11 @@ namespace AsbCloudWebApi.Tests.ServicesTests
Surname = "Тестович" Surname = "Тестович"
} }
}; };
private ICrudService<DrillerDto> service; private ICrudRepository<DrillerDto> service;
public DrillerServiceTest() public DrillerServiceTest()
{ {
var repositoryMock = RepositoryFactory.Make<ICrudService<DrillerDto>, DrillerDto>(Drillers); var repositoryMock = RepositoryFactory.Make<ICrudRepository<DrillerDto>, DrillerDto>(Drillers);
repositoryMock.Setup(x => x.GetAllAsync(It.IsAny<CancellationToken>())) repositoryMock.Setup(x => x.GetAllAsync(It.IsAny<CancellationToken>()))
.Returns(() => { .Returns(() => {

View File

@ -11,9 +11,9 @@ namespace AsbCloudWebApi.Controllers
[Route("api/admin/cluster")] [Route("api/admin/cluster")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class AdminClusterController : CrudController<ClusterDto, ICrudService<ClusterDto>> public class AdminClusterController : CrudController<ClusterDto, ICrudRepository<ClusterDto>>
{ {
public AdminClusterController(ICrudService<ClusterDto> service) public AdminClusterController(ICrudRepository<ClusterDto> service)
: base(service) : base(service)
{ } { }
} }

View File

@ -11,9 +11,9 @@ namespace AsbCloudWebApi.Controllers
[Route("api/admin/company")] [Route("api/admin/company")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class AdminCompanyController : CrudController<CompanyDto, ICrudService<CompanyDto>> public class AdminCompanyController : CrudController<CompanyDto, ICrudRepository<CompanyDto>>
{ {
public AdminCompanyController(ICrudService<CompanyDto> service) public AdminCompanyController(ICrudRepository<CompanyDto> service)
: base(service) : base(service)
{ {
} }

View File

@ -11,9 +11,9 @@ namespace AsbCloudWebApi.Controllers
[Route("api/admin/companyType")] [Route("api/admin/companyType")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class AdminCompanyTypeController : CrudController<CompanyTypeDto, ICrudService<CompanyTypeDto>> public class AdminCompanyTypeController : CrudController<CompanyTypeDto, ICrudRepository<CompanyTypeDto>>
{ {
public AdminCompanyTypeController(ICrudService<CompanyTypeDto> service) public AdminCompanyTypeController(ICrudRepository<CompanyTypeDto> service)
: base(service) : base(service)
{ } { }
} }

View File

@ -11,9 +11,9 @@ namespace AsbCloudWebApi.Controllers
[Route("api/admin/deposit")] [Route("api/admin/deposit")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class AdminDepositController : CrudController<DepositDto, ICrudService<DepositDto>> public class AdminDepositController : CrudController<DepositDto, ICrudRepository<DepositDto>>
{ {
public AdminDepositController(ICrudService<DepositDto> service) public AdminDepositController(ICrudRepository<DepositDto> service)
: base(service) : base(service)
{ {
} }

View File

@ -15,9 +15,9 @@ namespace AsbCloudWebApi.Controllers
[Route("api/admin/permission")] [Route("api/admin/permission")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class AdminPermissionController : CrudController<PermissionDto, ICrudService<PermissionDto>> public class AdminPermissionController : CrudController<PermissionDto, ICrudRepository<PermissionDto>>
{ {
public AdminPermissionController(ICrudService<PermissionDto> service) public AdminPermissionController(ICrudRepository<PermissionDto> service)
: base(service) : base(service)
{ } { }

View File

@ -13,11 +13,11 @@ namespace AsbCloudWebApi.Controllers
[Route("api/admin/telemetry")] [Route("api/admin/telemetry")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class AdminTelemetryController : CrudController<TelemetryDto, ICrudService<TelemetryDto>> public class AdminTelemetryController : CrudController<TelemetryDto, ICrudRepository<TelemetryDto>>
{ {
private readonly ITelemetryService telemetryService; private readonly ITelemetryService telemetryService;
public AdminTelemetryController(ICrudService<TelemetryDto> service, public AdminTelemetryController(ICrudRepository<TelemetryDto> service,
ITelemetryService telemetryService) ITelemetryService telemetryService)
: base(service) : base(service)
{ {

View File

@ -13,7 +13,7 @@ namespace AsbCloudWebApi.Controllers
[Route("api/admin/user")] [Route("api/admin/user")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class AdminUserController : CrudController<UserExtendedDto, ICrudService<UserExtendedDto>> public class AdminUserController : CrudController<UserExtendedDto, ICrudRepository<UserExtendedDto>>
{ {
public AdminUserController(IUserRepository service) public AdminUserController(IUserRepository service)
: base(service) : base(service)

View File

@ -13,7 +13,7 @@ namespace AsbCloudWebApi.Controllers
[Route("api/admin/well")] [Route("api/admin/well")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class AdminWellController : CrudController<WellDto, ICrudService<WellDto>> public class AdminWellController : CrudController<WellDto, ICrudRepository<WellDto>>
{ {
public AdminWellController(IWellService service) public AdminWellController(IWellService service)
: base(service) : base(service)

View File

@ -21,7 +21,7 @@ namespace AsbCloudWebApi.Controllers
[Authorize] [Authorize]
public abstract class CrudController<T, TService> : ControllerBase public abstract class CrudController<T, TService> : ControllerBase
where T : IId where T : IId
where TService : ICrudService<T> where TService : ICrudRepository<T>
{ {
protected readonly TService service; protected readonly TService service;
@ -115,7 +115,7 @@ namespace AsbCloudWebApi.Controllers
return Forbid(); return Forbid();
var result = await service.UpdateAsync(value, token).ConfigureAwait(false); var result = await service.UpdateAsync(value, token).ConfigureAwait(false);
if (result == ICrudService<T>.ErrorIdNotFound) if (result == ICrudRepository<T>.ErrorIdNotFound)
return BadRequest($"id:{value.Id} does not exist in the db"); return BadRequest($"id:{value.Id} does not exist in the db");
return Ok(result); return Ok(result);
} }
@ -134,7 +134,7 @@ namespace AsbCloudWebApi.Controllers
return Forbid(); return Forbid();
var result = await service.DeleteAsync(id, token).ConfigureAwait(false); var result = await service.DeleteAsync(id, token).ConfigureAwait(false);
if (result == ICrudService<T>.ErrorIdNotFound) if (result == ICrudRepository<T>.ErrorIdNotFound)
return NoContent(); return NoContent();
return Ok(result); return Ok(result);
} }

View File

@ -11,9 +11,9 @@ namespace AsbCloudWebApi.Controllers
[Route("api/driller")] [Route("api/driller")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class DrillerController : CrudController<DrillerDto, ICrudService<DrillerDto>> public class DrillerController : CrudController<DrillerDto, ICrudRepository<DrillerDto>>
{ {
public DrillerController(ICrudService<DrillerDto> service) public DrillerController(ICrudRepository<DrillerDto> service)
: base(service) : base(service)
{ } { }
} }

View File

@ -11,9 +11,9 @@ namespace AsbCloudWebApi.Controllers
[Route("api/[Controller]")] [Route("api/[Controller]")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class FileCategoryController : CrudController<FileCategoryDto, ICrudService<FileCategoryDto>> public class FileCategoryController : CrudController<FileCategoryDto, ICrudRepository<FileCategoryDto>>
{ {
public FileCategoryController(ICrudService<FileCategoryDto> service, IFileCategoryService fileCategoryService) public FileCategoryController(ICrudRepository<FileCategoryDto> service, IFileCategoryService fileCategoryService)
: base(service) : base(service)
{ {
} }

View File

@ -12,9 +12,9 @@ namespace AsbCloudWebApi.Controllers.Subsystems
[Route("api/admin/subsystem")] [Route("api/admin/subsystem")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class AdminSubsystemController : CrudController<SubsystemDto, ICrudService<SubsystemDto>> public class AdminSubsystemController : CrudController<SubsystemDto, ICrudRepository<SubsystemDto>>
{ {
public AdminSubsystemController(ICrudService<SubsystemDto> service) public AdminSubsystemController(ICrudRepository<SubsystemDto> service)
: base(service) : base(service)
{ {
} }