using Mapster; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Persistence.Database.Entity; using Persistence.Models; using Persistence.Repositories; using Persistence.Repository.Extensions; namespace Persistence.Repository.Repositories { public class TechMessagesRepository : ITechMessagesRepository { private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DrillingSystem).FullName}CacheKey"; private const int CacheExpirationInMinutes = 60; private readonly IMemoryCache memoryCache; private DbContext db; public TechMessagesRepository(DbContext db, IMemoryCache memoryCache) { this.memoryCache = memoryCache; this.db = db; } protected virtual IQueryable GetQueryReadOnly() => db.Set() .Include(e => e.System); public async Task> GetPage(RequestDto request, CancellationToken token) { var query = GetQueryReadOnly(); var count = await query.CountAsync(token); var sort = request.SortSettings != string.Empty ? request.SortSettings : nameof(TechMessage.Timestamp); var entities = await query .SortBy(request.SortSettings) .Skip(request.Skip) .Take(request.Take) .ToArrayAsync(token); var dto = new PaginationContainer() { Skip = request.Skip, Take = request.Take, Count = count, Items = entities.Select(e => e.Adapt()) }; return dto; } public async Task> GetStatistics(IEnumerable autoDrillingSystem, IEnumerable categoryIds, CancellationToken token) { var query = GetQueryReadOnly(); var systems = autoDrillingSystem.Select(s => s.ToLower().Trim()); var result = await query .Where(e => systems.Count() == 0 || systems.Contains(e.System.Name.ToLower().Trim())) .GroupBy(e => e.System.Name, (key, group) => new { System = key, Categories = group .Where(g => categoryIds.Count() == 0 || categoryIds.Contains(g.CategoryId)) }) .ToArrayAsync(token); var entities = new List(); foreach (var e in result) { var categories = e.Categories .GroupBy(g => g.CategoryId) .ToDictionary(c => c.Key, v => v.Count()); var entity = new MessagesStatisticDto() { System = e.System, Categories = categories }; entities.Add(entity); } return entities; } public async Task> GetSystems(CancellationToken token) { var entities = await GetDrillingSystems(token); var result = entities.Select(e => e.Name); return result; } public async Task InsertRange(IEnumerable dtos, CancellationToken token) { var entities = new List(); foreach (var dto in dtos) { var entity = dto.Adapt(); var systems = await GetDrillingSystems(token); var systemId = systems.FirstOrDefault(e => e.Name.ToLower().Trim() == dto.System.ToLower().Trim())?.SystemId ?? await CreateDrillingSystem(dto.System, token); entity.SystemId = systemId; entities.Add(entity); } await db.Set().AddRangeAsync(entities, token); var result = await db.SaveChangesAsync(token); return result; } public async Task> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token) { var query = GetQueryReadOnly(); var entities = await query .Where(e => e.Timestamp > dateBegin) .Take(take) .ToArrayAsync(token); var dtos = entities .Select(e => e.Adapt()); return dtos; } public async Task GetDatesRangeAsync(CancellationToken token) { var query = GetQueryReadOnly() .GroupBy(e => 1) .Select(group => new { Min = group.Min(e => e.Timestamp), Max = group.Max(e => e.Timestamp), }); var values = await query.FirstOrDefaultAsync(token); var result = new DatesRangeDto() { From = values?.Min ?? DateTimeOffset.MinValue, To = values?.Max ?? DateTimeOffset.MaxValue }; return result; } private async Task> GetDrillingSystems(CancellationToken token) { var systems = await memoryCache.GetOrCreateAsync(SystemCacheKey, async f => { f.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(CacheExpirationInMinutes); var query = db.Set(); var entities = await query.ToListAsync(token); var dtos = entities.Select(e => e.Adapt()); return dtos; }); return systems!; } private async Task CreateDrillingSystem(string name, CancellationToken token) { memoryCache.Remove(SystemCacheKey); var entity = new Database.Entity.DrillingSystem() { SystemId = default, Name = name.ToLower().Trim() }; await db.Set().AddAsync(entity); await db.SaveChangesAsync(token); return entity.SystemId; } } }