using AsbCloudApp.Data.DetectedOperation; using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb; using AsbCloudDb.Model; using Mapster; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Repository; public class DetectedOperationRepository : CrudRepositoryBase, IDetectedOperationRepository { private readonly ITelemetryService telemetryService; public DetectedOperationRepository(IAsbCloudDbContext context, ITelemetryService telemetryService) : base(context) { this.telemetryService = telemetryService; } public async Task Delete(int idUser, DetectedOperationByTelemetryRequest request, CancellationToken token) { var query = BuildQuery(request); dbContext.Set().RemoveRange(query); return await dbContext.SaveChangesAsync(token); } public async Task DeleteRange(int idUser, IEnumerable ids, CancellationToken token) { var query = dbContext.Set() .Where(e => ids.Contains( e.Id)); dbContext.Set() .RemoveRange(query); return await dbContext.SaveChangesAsync(token); } public async Task> GetLastDetectedDatesAsync(CancellationToken token) => await dbContext.Set() .GroupBy(o => o.IdTelemetry) .Select(g => new { IdTelemetry = g.Key, LastDate = g.Max(o => o.DateEnd) }) .ToDictionaryAsync(x => x.IdTelemetry, x => x.LastDate, token); public async Task> Get(DetectedOperationByTelemetryRequest request, CancellationToken token) { var query = BuildQuery(request) .Include(o => o.OperationCategory); var entities = await query.ToArrayAsync(token); var dtos = entities.Select(Convert); return dtos; } public async Task Insert(int? idUser, IEnumerable dtos, CancellationToken token) { if(!dtos.Any()) return 0; var entities = dtos.Select(Convert); var dbset = dbContext.Set(); foreach(var entity in entities) { entity.Id = default; dbset.Add(entity); } return await dbContext.SaveChangesWithExceptionHandling(token); } public async Task Update(int idUser, IEnumerable dtos, CancellationToken token) { if (!dtos.Any()) return 0; var ids = dtos .Select(o => o.Id) .Distinct() .ToArray(); if (ids.Any(id => id == default)) throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь Id"); if (ids.Length != dtos.Count()) throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь уникальные Id"); var dbSet = dbContext.Set(); var existingEntitiesCount = await dbSet .Where(o => ids.Contains(o.Id)) .CountAsync(token); if (ids.Length != existingEntitiesCount) throw new ArgumentInvalidException(nameof(dtos), "Все записи должны существовать в БД"); var entities = dtos .Select(Convert) .ToArray(); var entries = new Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry[entities.Length]; for(var i = 0; i < entities.Length; i++) entries[i] = dbSet.Update(entities[i]); var result = await dbContext.SaveChangesWithExceptionHandling(token); for (var i = 0; i < entries.Length; i++) entries[i].State = EntityState.Detached; return result; } public async Task UpdateOrInsert(int idUser, IEnumerable dtos, CancellationToken token) { var result = 0; var itemsToInsert = dtos.Where(e => e.Id == 0); if (itemsToInsert.Any()) result += await Insert(idUser, itemsToInsert, token); var itemsToUpdate = dtos.Where(e => e.Id != 0); if (itemsToUpdate.Any()) result += await Update(idUser, itemsToUpdate, token); return result; } private IQueryable BuildQuery(DetectedOperationByTelemetryRequest request) { var query = dbContext.Set() .Where(o => o.IdTelemetry == request.IdTelemetry); if (request.IdsCategories.Any()) query = query.Where(o => request.IdsCategories.Contains(o.IdCategory)); if (request.GeDepthStart is not null) query = query.Where(o => o.DepthStart >= request.GeDepthStart); if (request.LeDepthEnd is not null) query = query.Where(o => o.DepthEnd <= request.LeDepthEnd); if (request.GeDateStart is not null) { var geDate = request.GeDateStart.Value.ToUniversalTime(); query = query.Where(o => o.DateStart >= geDate); } if (request.LeDateEnd is not null) { var leDate = request.LeDateEnd.Value.ToUniversalTime(); query = query.Where(o => o.DateEnd <= leDate); } if (request.SortFields?.Any() == true) { query = query.SortBy(request.SortFields); } else query = query .OrderBy(o => o.DateStart) .ThenBy(o => o.DepthStart); if (request.Skip.HasValue) query = query.Skip((int)request.Skip); if (request.Take.HasValue) query = query.Take((int)request.Take); return query; } protected override DetectedOperationDto Convert(DetectedOperation src) { var timezone = telemetryService.GetTimezone(src.IdTelemetry); var dto = src.Adapt(); dto.DateStart = src.DateStart.ToOffset(timezone.Offset); dto.DateEnd = src.DateEnd.ToOffset(timezone.Offset); return dto; } protected override DetectedOperation Convert(DetectedOperationDto src) { var entity = src.Adapt(); entity.DateStart = src.DateStart.ToUniversalTime(); entity.DateEnd = src.DateEnd.ToUniversalTime(); return entity; } }