: ITimestampedValuesRepository GetQueryReadOnly() => this.db.Set();
- public virtual async Task GetDatesRange(CancellationToken token)
+ public virtual async Task GetDatesRange(Guid discriminatorId, CancellationToken token)
{
- var query = GetQueryReadOnly();
- var minDate = await query.MinAsync(o => o.Timestamp, token);
- var maxDate = await query.MaxAsync(o => o.Timestamp, token);
+ var query = GetQueryReadOnly()
+ .GroupBy(entity => entity.DiscriminatorId)
+ .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 = minDate,
- To = maxDate
+ From = item.Min,
+ To = item.Max,
};
}
- public virtual async Task> GetGtDate(DateTimeOffset date, CancellationToken token)
+ public virtual async Task> GetGtDate(Guid discriminatorId, DateTimeOffset date, CancellationToken token)
{
var query = GetQueryReadOnly().Where(e => e.Timestamp > date);
var entities = await query.ToArrayAsync(token);
@@ -41,9 +51,13 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository AddRange(IEnumerable dtos, CancellationToken token)
+ public virtual async Task AddRange(Guid discriminatorId, IEnumerable dtos, CancellationToken token)
{
- var entities = dtos.Select(d => d.Adapt());
+ var entities = dtos
+ .Select(d => d.Adapt())
+ .ToList();
+
+ entities.ForEach(d => d.DiscriminatorId = discriminatorId);
await db.Set().AddRangeAsync(entities, token);
var result = await db.SaveChangesAsync(token);
@@ -78,12 +92,13 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository> GetResampledData(
+ Guid discriminatorId,
DateTimeOffset dateBegin,
double intervalSec = 600d,
int approxPointsCount = 1024,
CancellationToken token = default)
{
- var dtos = await GetGtDate(dateBegin, token);
+ var dtos = await GetGtDate(discriminatorId, dateBegin, token);
var dateEnd = dateBegin.AddSeconds(intervalSec);
dtos = dtos
@@ -96,4 +111,77 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token)
+ {
+ var dbSet = db.Set();
+ var query = dbSet.Where(entity => entity.DiscriminatorId == idDiscriminator);
+
+ if (geTimestamp.HasValue)
+ query = ApplyGeTimestamp(query, geTimestamp.Value);
+
+ query = query
+ .OrderBy(item => item.Timestamp)
+ .Skip(skip)
+ .Take(take);
+
+ var data = await Materialize(query, token);
+
+ if (columnNames is not null && columnNames.Any())
+ data = ReduceSetColumnsByNames(data, columnNames);
+
+ return data;
+ }
+
+ public async Task> GetLast(Guid idDiscriminator, IEnumerable? columnNames, int take, CancellationToken token)
+ {
+ var dbSet = db.Set();
+ var query = dbSet.Where(entity => entity.DiscriminatorId == idDiscriminator);
+
+ query = query.OrderByDescending(entity => entity.Timestamp)
+ .Take(take)
+ .OrderBy(entity => entity.Timestamp);
+
+ var data = await Materialize(query, token);
+
+ if (columnNames is not null && columnNames.Any())
+ data = ReduceSetColumnsByNames(data, columnNames);
+
+ return data;
+ }
+
+ public Task Count(Guid idDiscriminator, CancellationToken token)
+ {
+ var dbSet = db.Set();
+ var query = dbSet.Where(entity => entity.DiscriminatorId == idDiscriminator);
+ return query.CountAsync(token);
+ }
+
+ private static async Task> Materialize(IQueryable query, CancellationToken token)
+ {
+ var dtoQuery = query.Select(entity => new TimestampedValuesDto() { Timestamp = entity.Timestamp, Values = entity.Values });
+ var dtos = await dtoQuery.ToArrayAsync(token);
+ return dtos;
+ }
+
+ private static IQueryable ApplyGeTimestamp(IQueryable query, DateTimeOffset geTimestamp)
+ {
+ var geTimestampUtc = geTimestamp.ToUniversalTime();
+ return query.Where(entity => entity.Timestamp >= geTimestampUtc);
+ }
+
+ private static IEnumerable ReduceSetColumnsByNames(IEnumerable query, IEnumerable columnNames)
+ {
+ var newQuery = query
+ .Select(entity => new TimestampedValuesDto()
+ {
+ Timestamp = entity.Timestamp,
+ Values = entity.Values?
+ .Where(prop => columnNames.Contains(
+ JsonSerializer.Deserialize>(prop.ToString()!)?
+ .FirstOrDefault().Key
+ )).ToArray()
+ });
+ return newQuery;
+ }
}
diff --git a/DD.Persistence/Models/TimestampedSetDto.cs b/DD.Persistence/Models/TimestampedValuesDto.cs
similarity index 62%
rename from DD.Persistence/Models/TimestampedSetDto.cs
rename to DD.Persistence/Models/TimestampedValuesDto.cs
index 20c5cbb..938970d 100644
--- a/DD.Persistence/Models/TimestampedSetDto.cs
+++ b/DD.Persistence/Models/TimestampedValuesDto.cs
@@ -1,9 +1,11 @@
-namespace DD.Persistence.Models;
+using DD.Persistence.ModelsAbstractions;
+
+namespace DD.Persistence.Models;
///
/// Набор данных с отметкой времени
///
-public class TimestampedSetDto
+public class TimestampedValuesDto : ITimestampAbstractDto
{
///
/// Временная отметка
@@ -13,5 +15,5 @@ public class TimestampedSetDto
///
/// Набор данных
///
- public required object[] Set { get; set; }
+ public object[]? Values { get; set; }
}
diff --git a/DD.Persistence/Repositories/ITimestampedSetRepository.cs b/DD.Persistence/Repositories/ITimestampedSetRepository.cs
deleted file mode 100644
index c448744..0000000
--- a/DD.Persistence/Repositories/ITimestampedSetRepository.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using DD.Persistence.Models;
-using DD.Persistence.Models.Common;
-
-namespace DD.Persistence.Repositories;
-
-///
-/// Репозиторий для хранения разных наборов данных рядов.
-/// idDiscriminator - идентифицирует конкретный набор данных, прим.: циклы измерения АСИБР, или отчет о DrillTest.
-/// idDiscriminator формируют клиенты и только им известно что они обозначают.
-/// Так как данные приходят редко, то их прореживания для построения графиков не предусмотрено.
-///
-public interface ITimestampedSetRepository
-{
- ///
- /// Количество записей по указанному набору в БД. Для пагинации.
- ///
- /// Дискриминатор (идентификатор) набора
- ///
- ///
- Task Count(Guid idDiscriminator, CancellationToken token);
-
- ///
- /// Получение данных с фильтрацией. Значение фильтра null - отключен
- ///
- /// Дискриминатор (идентификатор) набора
- /// Фильтр позднее даты
- /// Фильтр свойств набора. Можно запросить только некоторые свойства из набора
- ///
- ///
- ///
- ///
- Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token);
-
- ///
- /// Диапазон дат за которые есть данные
- ///
- /// Дискриминатор (идентификатор) набора
- ///
- ///
- Task GetDatesRange(Guid idDiscriminator, CancellationToken token);
-
- ///
- /// Получить последние данные
- ///
- /// Дискриминатор (идентификатор) набора
- /// Фильтр свойств набора. Можно запросить только некоторые свойства из набора
- ///
- ///
- ///
- Task> GetLast(Guid idDiscriminator, IEnumerable? columnNames, int take, CancellationToken token);
-
- ///
- /// Добавление новых данных
- ///
- /// Дискриминатор (идентификатор) набора
- ///
- ///
- ///
- Task AddRange(Guid idDiscriminator, IEnumerable sets, CancellationToken token);
-}
\ No newline at end of file
diff --git a/DD.Persistence/Repositories/ITimestampedValuesRepository.cs b/DD.Persistence/Repositories/ITimestampedValuesRepository.cs
index 447d197..5a508c4 100644
--- a/DD.Persistence/Repositories/ITimestampedValuesRepository.cs
+++ b/DD.Persistence/Repositories/ITimestampedValuesRepository.cs
@@ -1,5 +1,6 @@
using DD.Persistence.Models;
using DD.Persistence.ModelsAbstractions;
+using DD.Persistence.RepositoriesAbstractions;
namespace DD.Persistence.Repositories;
@@ -7,14 +8,45 @@ namespace DD.Persistence.Repositories;
/// Интерфейс по работе с временными данными
///
///
-public interface ITimestampedValuesRepository : ISyncRepository, ITimeSeriesBaseRepository
+public interface ITimestampedValuesRepository : ISyncRepository, ITimeSeriesBaseRepository
where TDto : class, ITimestampAbstractDto, new()
{
///
/// Добавление записей
///
+ ///
///
///
///
- Task AddRange(IEnumerable dtos, CancellationToken token);
+ Task AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token);
+
+ ///
+ /// Количество записей по указанному набору в БД. Для пагинации.
+ ///
+ /// Дискриминатор (идентификатор) набора
+ ///
+ ///
+ Task Count(Guid idDiscriminator, CancellationToken token);
+
+ ///
+ /// Получить последние данные
+ ///
+ /// Дискриминатор (идентификатор) набора
+ /// Фильтр свойств набора. Можно запросить только некоторые свойства из набора
+ ///
+ ///
+ ///
+ Task> GetLast(Guid idDiscriminator, IEnumerable? columnNames, int take, CancellationToken token);
+
+ ///
+ /// Получение данных с фильтрацией. Значение фильтра null - отключен
+ ///
+ /// Дискриминатор (идентификатор) набора
+ /// Фильтр позднее даты
+ /// Фильтр свойств набора. Можно запросить только некоторые свойства из набора
+ ///
+ ///
+ ///
+ ///
+ Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token);
}
diff --git a/DD.Persistence/Repositories/ISyncRepository.cs b/DD.Persistence/RepositoriesAbstractions/ISyncRepository.cs
similarity index 60%
rename from DD.Persistence/Repositories/ISyncRepository.cs
rename to DD.Persistence/RepositoriesAbstractions/ISyncRepository.cs
index 9a43b01..4db2645 100644
--- a/DD.Persistence/Repositories/ISyncRepository.cs
+++ b/DD.Persistence/RepositoriesAbstractions/ISyncRepository.cs
@@ -1,6 +1,6 @@
using DD.Persistence.Models.Common;
-namespace DD.Persistence.Repositories;
+namespace DD.Persistence.RepositoriesAbstractions;
///
/// Интерфейс по работе с данными
@@ -11,15 +11,18 @@ public interface ISyncRepository
///
/// Получить данные, начиная с определенной даты
///
+ ///
/// дата начала
- /// ///
- Task> GetGtDate(DateTimeOffset dateBegin, CancellationToken token);
+ ///
+ ///
+ Task> GetGtDate(Guid discriminatorId, DateTimeOffset dateBegin, CancellationToken token);
///
/// Получить диапазон дат, для которых есть данные в репозитории
///
+ ///
///
///
- Task GetDatesRange(CancellationToken token);
+ Task GetDatesRange(Guid discriminatorId, CancellationToken token);
}
diff --git a/DD.Persistence/Repositories/ITimeSeriesBaseRepository.cs b/DD.Persistence/RepositoriesAbstractions/ITimeSeriesBaseRepository.cs
similarity index 65%
rename from DD.Persistence/Repositories/ITimeSeriesBaseRepository.cs
rename to DD.Persistence/RepositoriesAbstractions/ITimeSeriesBaseRepository.cs
index 5f472e0..9fd43b4 100644
--- a/DD.Persistence/Repositories/ITimeSeriesBaseRepository.cs
+++ b/DD.Persistence/RepositoriesAbstractions/ITimeSeriesBaseRepository.cs
@@ -1,19 +1,23 @@
using DD.Persistence.Models;
-namespace DD.Persistence.Repositories;
+namespace DD.Persistence.RepositoriesAbstractions;
///
/// Интерфейс по работе с прореженными данными
///
-public interface ITimeSeriesBaseRepository
+public interface ITimeSeriesBaseRepository
{
///
/// Получить список объектов с прореживанием
///
+ ///
/// дата начала
+ ///
///
+ ///
///
- Task> GetResampledData(
+ Task> GetResampledData(
+ Guid discriminatorId,
DateTimeOffset dateBegin,
double intervalSec = 600d,
int approxPointsCount = 1024,
| | | |