2024-11-22 17:52:15 +05:00
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
|
using Persistence.Database.Entity;
|
|
|
|
|
using Persistence.Models;
|
|
|
|
|
using Persistence.Repositories;
|
|
|
|
|
|
|
|
|
|
namespace Persistence.Repository.Repositories;
|
2024-11-25 09:41:11 +05:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Репозиторий для хранения разных наборов данных временных рядов.
|
|
|
|
|
/// idDiscriminator - идентифицирует конкретный набор данных, прим.: циклы измерения АСИБР, или отчет о DrillTest.
|
|
|
|
|
/// idDiscriminator формируют клиенты и только им известно что они обозначают.
|
|
|
|
|
/// Так как данные приходят редко, то их прореживания для построения графиков не предусмотрено.
|
|
|
|
|
/// </summary>
|
2024-11-22 17:52:15 +05:00
|
|
|
|
public class TimestampedSetRepository : ITimestampedSetRepository
|
|
|
|
|
{
|
2024-11-26 10:07:50 +05:00
|
|
|
|
private readonly DbContext db;
|
2024-11-22 17:52:15 +05:00
|
|
|
|
|
2024-11-26 10:07:50 +05:00
|
|
|
|
public TimestampedSetRepository(DbContext db)
|
2024-11-22 17:52:15 +05:00
|
|
|
|
{
|
|
|
|
|
this.db = db;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task<int> InsertRange(Guid idDiscriminator, IEnumerable<TimestampedSetDto> sets, CancellationToken token)
|
|
|
|
|
{
|
|
|
|
|
var entities = sets.Select(set => new TimestampedSet(idDiscriminator, set.Timestamp.ToUniversalTime(), set.Set));
|
|
|
|
|
var dbSet = db.Set<TimestampedSet>();
|
|
|
|
|
dbSet.AddRange(entities);
|
|
|
|
|
return db.SaveChangesAsync(token);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-26 11:24:31 +05:00
|
|
|
|
public async Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
|
2024-11-22 17:52:15 +05:00
|
|
|
|
{
|
|
|
|
|
var dbSet = db.Set<TimestampedSet>();
|
|
|
|
|
var query = dbSet.Where(entity => entity.IdDiscriminator == idDiscriminator);
|
|
|
|
|
|
|
|
|
|
if (geTimestamp.HasValue)
|
|
|
|
|
query = ApplyGeTimestamp(query, geTimestamp.Value);
|
|
|
|
|
|
2024-11-26 10:07:50 +05:00
|
|
|
|
query = query
|
|
|
|
|
.OrderBy(item => item.Timestamp)
|
|
|
|
|
.Skip(skip)
|
|
|
|
|
.Take(take);
|
|
|
|
|
|
2024-11-22 17:52:15 +05:00
|
|
|
|
var data = await Materialize(query, token);
|
|
|
|
|
|
2024-11-26 11:24:31 +05:00
|
|
|
|
if (columnNames is not null && columnNames.Any())
|
|
|
|
|
data = ReduceSetColumnsByNames(data, columnNames);
|
2024-11-22 17:52:15 +05:00
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-26 11:24:31 +05:00
|
|
|
|
public async Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? columnNames, int take, CancellationToken token)
|
2024-11-22 17:52:15 +05:00
|
|
|
|
{
|
|
|
|
|
var dbSet = db.Set<TimestampedSet>();
|
|
|
|
|
var query = dbSet.Where(entity => entity.IdDiscriminator == idDiscriminator);
|
|
|
|
|
|
|
|
|
|
query = query.OrderByDescending(entity => entity.Timestamp)
|
|
|
|
|
.Take(take)
|
|
|
|
|
.OrderBy(entity => entity.Timestamp);
|
|
|
|
|
|
|
|
|
|
var data = await Materialize(query, token);
|
|
|
|
|
|
2024-11-26 11:24:31 +05:00
|
|
|
|
if (columnNames is not null && columnNames.Any())
|
|
|
|
|
data = ReduceSetColumnsByNames(data, columnNames);
|
2024-11-22 17:52:15 +05:00
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task<int> Count(Guid idDiscriminator, CancellationToken token)
|
|
|
|
|
{
|
|
|
|
|
var dbSet = db.Set<TimestampedSet>();
|
|
|
|
|
var query = dbSet.Where(entity => entity.IdDiscriminator == idDiscriminator);
|
|
|
|
|
return query.CountAsync(token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token)
|
|
|
|
|
{
|
|
|
|
|
var query = db.Set<TimestampedSet>()
|
|
|
|
|
.GroupBy(entity => entity.IdDiscriminator)
|
|
|
|
|
.Select(group => new
|
|
|
|
|
{
|
|
|
|
|
Min = group.Min(entity => entity.Timestamp),
|
|
|
|
|
Max = group.Max(entity => entity.Timestamp),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var item = await query.FirstOrDefaultAsync(token);
|
|
|
|
|
if (item is null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
return new DatesRangeDto
|
|
|
|
|
{
|
|
|
|
|
From = item.Min,
|
|
|
|
|
To = item.Max,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static async Task<IEnumerable<TimestampedSetDto>> Materialize(IQueryable<TimestampedSet> query, CancellationToken token)
|
|
|
|
|
{
|
|
|
|
|
var dtoQuery = query.Select(entity => new TimestampedSetDto(entity.Timestamp, entity.Set));
|
|
|
|
|
var dtos = await dtoQuery.ToArrayAsync(token);
|
|
|
|
|
return dtos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IQueryable<TimestampedSet> ApplyGeTimestamp(IQueryable<TimestampedSet> query, DateTimeOffset geTimestamp)
|
|
|
|
|
{
|
|
|
|
|
var geTimestampUtc = geTimestamp.ToUniversalTime();
|
|
|
|
|
return query.Where(entity => entity.Timestamp >= geTimestampUtc);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-26 11:24:31 +05:00
|
|
|
|
private static IEnumerable<TimestampedSetDto> ReduceSetColumnsByNames(IEnumerable<TimestampedSetDto> query, IEnumerable<string> columnNames)
|
2024-11-22 17:52:15 +05:00
|
|
|
|
{
|
|
|
|
|
var newQuery = query
|
|
|
|
|
.Select(entity => new TimestampedSetDto(
|
|
|
|
|
entity.Timestamp,
|
|
|
|
|
entity.Set
|
2024-11-26 11:24:31 +05:00
|
|
|
|
.Where(prop => columnNames.Contains(prop.Key))
|
2024-11-22 17:52:15 +05:00
|
|
|
|
.ToDictionary(prop => prop.Key, prop => prop.Value)
|
|
|
|
|
));
|
|
|
|
|
return newQuery;
|
|
|
|
|
}
|
|
|
|
|
}
|