persistence/Persistence.Repository/Repositories/TimestampedSetRepository.cs

118 lines
4.5 KiB
C#
Raw Permalink Normal View History

2024-11-22 17:52:15 +05:00
using Microsoft.EntityFrameworkCore;
using Persistence.Database;
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
{
private readonly IPersistenceDbContext db;
public TimestampedSetRepository(IPersistenceDbContext db)
{
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);
}
public async Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? props, int skip, int take, CancellationToken token)
{
var dbSet = db.Set<TimestampedSet>();
var query = dbSet.Where(entity => entity.IdDiscriminator == idDiscriminator);
if (geTimestamp.HasValue)
query = ApplyGeTimestamp(query, geTimestamp.Value);
var data = await Materialize(query, token);
if (props is not null && props.Any())
data = ApplyPropsFilter(data, props);
return data;
}
public async Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? props, int take, CancellationToken token)
{
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);
if (props is not null && props.Any())
data = ApplyPropsFilter(data, props);
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);
}
private static IEnumerable<TimestampedSetDto> ApplyPropsFilter(IEnumerable<TimestampedSetDto> query, IEnumerable<string> props)
{
var newQuery = query
.Select(entity => new TimestampedSetDto(
entity.Timestamp,
entity.Set
.Where(prop => props.Contains(prop.Key))
.ToDictionary(prop => prop.Key, prop => prop.Value)
));
return newQuery;
}
}