using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.Cache; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services { public abstract class TelemetryDataService : ITelemetryDataService, IConverter where TDto : AsbCloudApp.Data.ITelemetryData where TModel : class, AsbCloudDb.Model.ITelemetryData { private readonly IAsbCloudDbContext db; private readonly ITelemetryService telemetryService; protected readonly CacheTable cacheTelemetry; protected readonly CacheTable cacheTelemetryUsers; protected readonly CacheTable cacheWells; public TelemetryDataService( IAsbCloudDbContext db, ITelemetryService telemetryService, CacheDb cacheDb) { this.db = db; this.telemetryService = telemetryService; cacheTelemetry = cacheDb.GetCachedTable((AsbCloudDbContext)db); cacheTelemetryUsers = cacheDb.GetCachedTable((AsbCloudDbContext)db); cacheWells = cacheDb.GetCachedTable((AsbCloudDbContext)db); } public virtual async Task UpdateDataAsync(string uid, IEnumerable dtos, CancellationToken token = default) { if (dtos == default || !dtos.Any()) return 0; var idTelemetry = telemetryService.GetOrCreateTemetryIdByUid(uid); var dtoMinDate = dtos.Min(d => d.Date); var dtoMaxDate = dtos.Max(d => d.Date); var dataSet = db.Set(); var oldData = await (from d in dataSet where d.IdTelemetry == idTelemetry && d.Date > dtoMinDate && d.Date < dtoMaxDate select d) .AsNoTracking() .ToListAsync(token) .ConfigureAwait(false); if (oldData.Any()) { dataSet.RemoveRange(oldData); await db.SaveChangesAsync(token).ConfigureAwait(false); } foreach (var dto in dtos) { dto.IdTelemetry = idTelemetry; var data = Convert(dto); data.Id = 0; dataSet.Add(data); } return await db.SaveChangesAsync(token).ConfigureAwait(false); } public virtual async Task> GetAsync(int idWell, DateTime dateBegin = default, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default) { var well = cacheWells.FirstOrDefault(w => w.Id == idWell); if (well is null) return default; var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == well.IdTelemetry); if (telemetry is null) return default; if (dateBegin == default) dateBegin = DateTime.Now.AddSeconds(-intervalSec); var datEnd = dateBegin.AddSeconds(intervalSec); var dbSet = db.Set(); var query = from data in dbSet where data.IdTelemetry == telemetry.Id && data.Date >= dateBegin && data.Date < datEnd select data; var fullDataCount = await query.CountAsync(token) .ConfigureAwait(false); if (fullDataCount == 0) return default; if (fullDataCount > 1.75 * approxPointsCount) { var m = (int)Math.Round(1d * fullDataCount / approxPointsCount); if (m > 1) query = query.Where(d => d.Id % m == 0); } var entities = await query.AsNoTracking() .ToListAsync(token).ConfigureAwait(false); var dtos = entities.Select(e => Convert(e)); return dtos; } public virtual async Task GetDataDatesRangeAsync(int idWell, CancellationToken token = default) { var telemetryId = telemetryService.GetIdTelemetryByIdWell(idWell); if (telemetryId is null) return null; var (From, To) = await db.GetDatesRangeAsync((int)telemetryId, token) .ConfigureAwait(false); return new DatesRangeDto { From = From, To = To }; } public abstract TDto Convert(TModel src); public abstract TModel Convert(TDto src); } }