Перевести TimestampedValuesRepository под спецификации

This commit is contained in:
Roman Efremov 2025-02-10 17:25:45 +05:00
parent 8e2c3a3a55
commit 2fe369d49e
37 changed files with 299 additions and 116 deletions

View File

@ -61,7 +61,7 @@ public class TimestampedValuesController : ControllerBase
int skip, int take, int skip, int take,
CancellationToken token) CancellationToken token)
{ {
var result = await timestampedValuesService.Get(discriminatorIds, timestampBegin, columnNames, skip, take, token); var result = await timestampedValuesService.Get(discriminatorIds, timestampBegin, filterTree, columnNames, skip, take, token);
return result.Any() ? Ok(result) : NoContent(); return result.Any() ? Ok(result) : NoContent();
} }

View File

@ -24,12 +24,14 @@ public interface ITimestampedValuesClient : IDisposable
/// </summary> /// </summary>
/// <param name="discriminatorIds">Набор дискриминаторов (идентификаторов)</param> /// <param name="discriminatorIds">Набор дискриминаторов (идентификаторов)</param>
/// <param name="timestampBegin">Фильтр позднее даты</param> /// <param name="timestampBegin">Фильтр позднее даты</param>
/// <param name="filterTree"></param>
/// <param name="columnNames">Фильтр свойств набора</param> /// <param name="columnNames">Фильтр свойств набора</param>
/// <param name="skip"></param> /// <param name="skip"></param>
/// <param name="take"></param> /// <param name="take"></param>
/// <param name="token"></param> /// <param name="token"></param>
Task<IEnumerable<TimestampedValuesDto>> Get(IEnumerable<Guid> discriminatorIds, Task<IEnumerable<TimestampedValuesDto>> Get(IEnumerable<Guid> discriminatorIds,
DateTimeOffset? timestampBegin, DateTimeOffset? timestampBegin,
string? filterTree,
IEnumerable<string>? columnNames, IEnumerable<string>? columnNames,
int skip, int skip,
int take, int take,
@ -40,11 +42,12 @@ public interface ITimestampedValuesClient : IDisposable
/// </summary> /// </summary>
/// <param name="discriminatorId"></param> /// <param name="discriminatorId"></param>
/// <param name="geTimestamp"></param> /// <param name="geTimestamp"></param>
/// <param name="filterTree"></param>
/// <param name="columnNames">Фильтр свойств набора</param> /// <param name="columnNames">Фильтр свойств набора</param>
/// <param name="skip"></param> /// <param name="skip"></param>
/// <param name="take"></param> /// <param name="take"></param>
/// <param name="token"></param> /// <param name="token"></param>
Task<IEnumerable<T>> Get<T>(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token); Task<IEnumerable<T>> Get<T>(Guid discriminatorId, DateTimeOffset? geTimestamp, string? filterTree, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token);
/// <summary> /// <summary>
/// Получить данные, начиная с заданной отметки времени /// Получить данные, начиная с заданной отметки времени

View File

@ -23,6 +23,7 @@ public interface IRefitTimestampedValuesClient : IRefitClient, IDisposable
[Get($"{baseUrl}")] [Get($"{baseUrl}")]
Task<IApiResponse<IEnumerable<TimestampedValuesDto>>> Get([Query(CollectionFormat.Multi)] IEnumerable<Guid> discriminatorIds, Task<IApiResponse<IEnumerable<TimestampedValuesDto>>> Get([Query(CollectionFormat.Multi)] IEnumerable<Guid> discriminatorIds,
DateTimeOffset? timestampBegin, DateTimeOffset? timestampBegin,
[Query] string? filterTree,
[Query(CollectionFormat.Multi)] IEnumerable<string>? columnNames, [Query(CollectionFormat.Multi)] IEnumerable<string>? columnNames,
int skip, int skip,
int take, int take,

View File

@ -32,17 +32,17 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient
} }
/// <inheritdoc/> /// <inheritdoc/>
public async Task<IEnumerable<TimestampedValuesDto>> Get(IEnumerable<Guid> discriminatorIds, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token) public async Task<IEnumerable<TimestampedValuesDto>> Get(IEnumerable<Guid> discriminatorIds, DateTimeOffset? geTimestamp, string? filterTree, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
{ {
var result = await ExecuteGetResponse( var result = await ExecuteGetResponse(
async () => await refitTimestampedSetClient.Get(discriminatorIds, geTimestamp, columnNames, skip, take, token), token); async () => await refitTimestampedSetClient.Get(discriminatorIds, geTimestamp, filterTree, columnNames, skip, take, token), token);
return result!; return result!;
} }
/// <inheritdoc/> /// <inheritdoc/>
public async Task<IEnumerable<T>> Get<T>(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token) public async Task<IEnumerable<T>> Get<T>(Guid discriminatorId, DateTimeOffset? geTimestamp, string? filterTree, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
{ {
var data = await Get([discriminatorId], geTimestamp, columnNames, skip, take, token); var data = await Get([discriminatorId], geTimestamp, filterTree, columnNames, skip, take, token);
var mapper = GetMapper<T>(discriminatorId); var mapper = GetMapper<T>(discriminatorId);
return data.Select(mapper.DeserializeTimeStampedData); return data.Select(mapper.DeserializeTimeStampedData);

View File

@ -13,7 +13,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace DD.Persistence.Database.Postgres.Migrations namespace DD.Persistence.Database.Postgres.Migrations
{ {
[DbContext(typeof(PersistencePostgresContext))] [DbContext(typeof(PersistencePostgresContext))]
[Migration("20250205114037_Init")] [Migration("20250210055116_Init")]
partial class Init partial class Init
{ {
/// <inheritdoc /> /// <inheritdoc />
@ -37,14 +37,14 @@ namespace DD.Persistence.Database.Postgres.Migrations
.HasColumnType("timestamp with time zone") .HasColumnType("timestamp with time zone")
.HasComment("Дата создания записи"); .HasComment("Дата создания записи");
b.Property<Guid>("DiscriminatorId")
.HasColumnType("uuid")
.HasComment("Дискриминатор таблицы");
b.Property<Guid>("IdAuthor") b.Property<Guid>("IdAuthor")
.HasColumnType("uuid") .HasColumnType("uuid")
.HasComment("Автор изменения"); .HasComment("Автор изменения");
b.Property<Guid>("IdDiscriminator")
.HasColumnType("uuid")
.HasComment("Дискриминатор таблицы");
b.Property<Guid?>("IdEditor") b.Property<Guid?>("IdEditor")
.HasColumnType("uuid") .HasColumnType("uuid")
.HasComment("Редактор"); .HasComment("Редактор");

View File

@ -17,7 +17,7 @@ namespace DD.Persistence.Database.Postgres.Migrations
columns: table => new columns: table => new
{ {
Id = table.Column<Guid>(type: "uuid", nullable: false, comment: "Ключ записи"), Id = table.Column<Guid>(type: "uuid", nullable: false, comment: "Ключ записи"),
IdDiscriminator = table.Column<Guid>(type: "uuid", nullable: false, comment: "Дискриминатор таблицы"), DiscriminatorId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Дискриминатор таблицы"),
IdAuthor = table.Column<Guid>(type: "uuid", nullable: false, comment: "Автор изменения"), IdAuthor = table.Column<Guid>(type: "uuid", nullable: false, comment: "Автор изменения"),
IdEditor = table.Column<Guid>(type: "uuid", nullable: true, comment: "Редактор"), IdEditor = table.Column<Guid>(type: "uuid", nullable: true, comment: "Редактор"),
Creation = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Дата создания записи"), Creation = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Дата создания записи"),

View File

@ -34,14 +34,14 @@ namespace DD.Persistence.Database.Postgres.Migrations
.HasColumnType("timestamp with time zone") .HasColumnType("timestamp with time zone")
.HasComment("Дата создания записи"); .HasComment("Дата создания записи");
b.Property<Guid>("DiscriminatorId")
.HasColumnType("uuid")
.HasComment("Дискриминатор таблицы");
b.Property<Guid>("IdAuthor") b.Property<Guid>("IdAuthor")
.HasColumnType("uuid") .HasColumnType("uuid")
.HasComment("Автор изменения"); .HasComment("Автор изменения");
b.Property<Guid>("IdDiscriminator")
.HasColumnType("uuid")
.HasComment("Дискриминатор таблицы");
b.Property<Guid?>("IdEditor") b.Property<Guid?>("IdEditor")
.HasColumnType("uuid") .HasColumnType("uuid")
.HasComment("Редактор"); .HasComment("Редактор");

View File

@ -42,6 +42,8 @@ public static class DependencyInjection
MapsterSetup(); MapsterSetup();
//services.AddTransient(typeof(PersistenceRepository<TimestampedValues>));
services.AddTransient<ISetpointRepository, SetpointRepository>(); services.AddTransient<ISetpointRepository, SetpointRepository>();
services.AddTransient<IChangeLogRepository, ChangeLogRepository>(); services.AddTransient<IChangeLogRepository, ChangeLogRepository>();
services.AddTransient<ITimestampedValuesRepository, TimestampedValuesRepository>(); services.AddTransient<ITimestampedValuesRepository, TimestampedValuesRepository>();

View File

@ -11,13 +11,13 @@ namespace DD.Persistence.Database.Entity;
/// Часть записи, описывающая изменение /// Часть записи, описывающая изменение
/// </summary> /// </summary>
[Table("change_log")] [Table("change_log")]
public class ChangeLog : IChangeLog public class ChangeLog : IDiscriminatorItem, IChangeLog
{ {
[Key, Comment("Ключ записи")] [Key, Comment("Ключ записи")]
public Guid Id { get; set; } public Guid Id { get; set; }
[Comment("Дискриминатор таблицы")] [Comment("Дискриминатор таблицы")]
public Guid IdDiscriminator { get; set; } public Guid DiscriminatorId { get; set; }
[Comment("Автор изменения")] [Comment("Автор изменения")]
public Guid IdAuthor { get; set; } public Guid IdAuthor { get; set; }

View File

@ -7,7 +7,7 @@ namespace DD.Persistence.Database.Entity;
[Table("parameter_data")] [Table("parameter_data")]
[PrimaryKey(nameof(DiscriminatorId), nameof(ParameterId), nameof(Timestamp))] [PrimaryKey(nameof(DiscriminatorId), nameof(ParameterId), nameof(Timestamp))]
public class ParameterData : ITimestampedItem public class ParameterData : IDiscriminatorItem, ITimestampedItem
{ {
[Required, Comment("Дискриминатор системы")] [Required, Comment("Дискриминатор системы")]
public Guid DiscriminatorId { get; set; } public Guid DiscriminatorId { get; set; }

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore; using DD.Persistence.Database.EntityAbstractions;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json; using System.Text.Json;
@ -7,7 +8,7 @@ namespace DD.Persistence.Database.Entity;
[Table("scheme_property")] [Table("scheme_property")]
[PrimaryKey(nameof(DiscriminatorId), nameof(Index))] [PrimaryKey(nameof(DiscriminatorId), nameof(Index))]
public class SchemeProperty public class SchemeProperty : IDiscriminatorItem
{ {
[Comment("Идентификатор схемы данных")] [Comment("Идентификатор схемы данных")]
public Guid DiscriminatorId { get; set; } public Guid DiscriminatorId { get; set; }

View File

@ -17,15 +17,15 @@ public class TechMessage : ITimestampedItem
[Comment("Дата возникновения")] [Comment("Дата возникновения")]
public DateTimeOffset Timestamp { get; set; } public DateTimeOffset Timestamp { get; set; }
[Column(TypeName = "varchar(512)"), Comment("Текст сообщения")] [Column(TypeName = "varchar(512)"), Comment("Текст сообщения")]
public required string Text { get; set; } public required string Text { get; set; }
[Required, Comment("Id системы, к которой относится сообщение")] [Required, Comment("Id системы, к которой относится сообщение")]
public required Guid SystemId { get; set; } public required Guid SystemId { get; set; }
[Required, ForeignKey(nameof(SystemId)), Comment("Система, к которой относится сообщение")] [Required, ForeignKey(nameof(SystemId)), Comment("Система, к которой относится сообщение")]
public virtual required DataSourceSystem System { get; set; } public virtual required DataSourceSystem System { get; set; }
[Comment("Статус события")] [Comment("Статус события")]
public int EventState { get; set; } public int EventState { get; set; }
} }

View File

@ -7,7 +7,7 @@ namespace DD.Persistence.Database.Entity;
[Table("timestamped_values")] [Table("timestamped_values")]
[PrimaryKey(nameof(DiscriminatorId), nameof(Timestamp))] [PrimaryKey(nameof(DiscriminatorId), nameof(Timestamp))]
public class TimestampedValues : ITimestampedItem, IValuesItem public class TimestampedValues : IDiscriminatorItem, ITimestampedItem, IValuesItem
{ {
[Comment("Временная отметка"), Key] [Comment("Временная отметка"), Key]
public DateTimeOffset Timestamp { get; set; } public DateTimeOffset Timestamp { get; set; }

View File

@ -38,7 +38,7 @@ public interface IChangeLog
/// <summary> /// <summary>
/// Дискриминатор таблицы /// Дискриминатор таблицы
/// </summary> /// </summary>
public Guid IdDiscriminator { get; set; } public Guid DiscriminatorId { get; set; }
/// <summary> /// <summary>
/// Значение /// Значение

View File

@ -0,0 +1,8 @@
namespace DD.Persistence.Database.EntityAbstractions;
public interface IDiscriminatorItem
{
/// <summary>
/// Дискриминатор
/// </summary>
Guid DiscriminatorId { get; set; }
}

View File

@ -36,3 +36,63 @@ public static class SpecificationExtensions
return newExpr; return newExpr;
} }
} }
public static class SpecificationBuilderExtensions
{
/// <summary>
/// Добавляет операцию GroupBy к спецификации.
/// </summary>
/// <typeparam name="TEntity">Тип сущности.</typeparam>
/// <typeparam name="TKey">Тип ключа группировки.</typeparam>
/// <param name="builder">Спецификация, к которой применяется GroupBy.</param>
/// <param name="keySelector">Выражение для выбора ключа группировки.</param>
/// <returns>Новый объект ISpecificationBuilder с примененной операцией GroupBy.</returns>
public static ISpecificationBuilderGrouping<TEntity, TKey> GroupBy<TEntity, TKey>(
this ISpecificationBuilder<TEntity> builder,
Expression<Func<TEntity, TKey>> keySelector)
{
if (builder is null)
throw new ArgumentNullException(nameof(builder));
if (keySelector is null)
throw new ArgumentNullException(nameof(keySelector));
var groupingSpecification = new GroupingSpecification<TEntity, TKey>(keySelector);
return new SpecificationBuilderGrouping<TEntity, TKey>(groupingSpecification);
}
}
public class GroupingSpecification<TEntity, TKey> : Specification<TEntity>
{
private readonly Expression<Func<TEntity, TKey>> _keySelector;
public GroupingSpecification(Expression<Func<TEntity, TKey>> keySelector)
{
_keySelector = keySelector ?? throw new ArgumentNullException(nameof(keySelector));
}
public Expression<Func<TEntity, TKey>> KeySelector => _keySelector;
}
public class SpecificationBuilderGrouping<TEntity, TKey> : ISpecificationBuilderGrouping<TEntity, TKey>
{
private readonly GroupingSpecification<TEntity, TKey> _specification;
public SpecificationBuilderGrouping(GroupingSpecification<TEntity, TKey> specification)
{
_specification = specification;
}
public ISpecification<TEntity> ToSpecification()
{
return _specification;
}
public GroupingSpecification<TEntity, TKey> UnderlyingSpecification => _specification;
public Specification<TEntity> Specification => UnderlyingSpecification;
}
public interface ISpecificationBuilderGrouping<TEntity, TKey> : ISpecificationBuilder<TEntity>
{
GroupingSpecification<TEntity, TKey> UnderlyingSpecification { get; }
}

View File

@ -1,8 +1,7 @@
using Ardalis.Specification; using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions; using DD.Persistence.Database.EntityAbstractions;
using DD.Persistence.Database.Postgres.Extensions; using DD.Persistence.Database.Specifications.Common.ValuesItem;
using DD.Persistence.Database.Specifications; using DD.Persistence.Database.Specifications.Operation;
using DD.Persistence.Database.Specifications.ValuesItem;
using DD.Persistence.Filter.Models; using DD.Persistence.Filter.Models;
using DD.Persistence.Filter.Models.Abstractions; using DD.Persistence.Filter.Models.Abstractions;
using DD.Persistence.Filter.Models.Enumerations; using DD.Persistence.Filter.Models.Enumerations;
@ -48,10 +47,10 @@ public static class FilterBuilder
switch (vertex.Operation) switch (vertex.Operation)
{ {
case OperationEnum.And: case OperationEnum.And:
result = new AndSpecification<TEntity>(leftSpecification, rigthSpecification); result = new AndSpec<TEntity>(leftSpecification, rigthSpecification);
break; break;
case OperationEnum.Or: case OperationEnum.Or:
result = new OrSpecification<TEntity>(leftSpecification, rigthSpecification); result = new OrSpec<TEntity>(leftSpecification, rigthSpecification);
break; break;
} }
@ -86,21 +85,21 @@ public static class FilterBuilder
private static Dictionary<OperationEnum, Func<int, string?, ISpecification<TEntity>>> StringSpecifications<TEntity>() private static Dictionary<OperationEnum, Func<int, string?, ISpecification<TEntity>>> StringSpecifications<TEntity>()
where TEntity : IValuesItem => new() where TEntity : IValuesItem => new()
{ {
{ OperationEnum.Equal, (int index, string? value) => new ValueEqaulSpecification<TEntity>(index, value) }, { OperationEnum.Equal, (int index, string? value) => new ValueEqaulSpec<TEntity>(index, value) },
{ OperationEnum.NotEqual, (int index, string? value) => new ValueNotEqualSpecification<TEntity>(index, value) }, { OperationEnum.NotEqual, (int index, string? value) => new ValueNotEqualSpec<TEntity>(index, value) },
{ OperationEnum.Greate, (int index, string? value) => new ValueGreateSpecification<TEntity>(index, value) }, { OperationEnum.Greate, (int index, string? value) => new ValueGreateSpec<TEntity>(index, value) },
{ OperationEnum.GreateOrEqual, (int index, string? value) => new ValueGreateOrEqualSpecification<TEntity>(index, value) }, { OperationEnum.GreateOrEqual, (int index, string? value) => new ValueGreateOrEqualSpec<TEntity>(index, value) },
{ OperationEnum.Less, (int index, string? value) => new ValueLessSpecification<TEntity>(index, value) }, { OperationEnum.Less, (int index, string? value) => new ValueLessSpec<TEntity>(index, value) },
{ OperationEnum.LessOrEqual, (int index, string? value) => new ValueLessOrEqualSpecification<TEntity>(index, value) } { OperationEnum.LessOrEqual, (int index, string? value) => new ValueLessOrEqualSpec<TEntity>(index, value) }
}; };
private static Dictionary<OperationEnum, Func<int, double?, ISpecification<TEntity>>> DoubleSpecifications<TEntity>() private static Dictionary<OperationEnum, Func<int, double?, ISpecification<TEntity>>> DoubleSpecifications<TEntity>()
where TEntity : IValuesItem => new() where TEntity : IValuesItem => new()
{ {
{ OperationEnum.Equal, (int index, double? value) => new ValueEqaulSpecification<TEntity>(index, value) }, { OperationEnum.Equal, (int index, double? value) => new ValueEqaulSpec<TEntity>(index, value) },
{ OperationEnum.NotEqual, (int index, double? value) => new ValueNotEqualSpecification<TEntity>(index, value) }, { OperationEnum.NotEqual, (int index, double? value) => new ValueNotEqualSpec<TEntity>(index, value) },
{ OperationEnum.Greate, (int index, double? value) => new ValueGreateSpecification<TEntity>(index, value) }, { OperationEnum.Greate, (int index, double? value) => new ValueGreateSpec<TEntity>(index, value) },
{ OperationEnum.GreateOrEqual, (int index, double? value) => new ValueGreateOrEqualSpecification<TEntity>(index, value) }, { OperationEnum.GreateOrEqual, (int index, double? value) => new ValueGreateOrEqualSpec<TEntity>(index, value) },
{ OperationEnum.Less, (int index, double? value) => new ValueLessSpecification<TEntity>(index, value) }, { OperationEnum.Less, (int index, double? value) => new ValueLessSpec<TEntity>(index, value) },
{ OperationEnum.LessOrEqual, (int index, double? value) => new ValueLessOrEqualSpecification<TEntity>(index, value) } { OperationEnum.LessOrEqual, (int index, double? value) => new ValueLessOrEqualSpec<TEntity>(index, value) }
}; };
} }

View File

@ -54,7 +54,7 @@ public class ChangeLogRepository : IChangeLogRepository
public async Task<int> MarkAsDeleted(Guid idEditor, Guid idDiscriminator, CancellationToken token) public async Task<int> MarkAsDeleted(Guid idEditor, Guid idDiscriminator, CancellationToken token)
{ {
var query = db.Set<ChangeLog>() var query = db.Set<ChangeLog>()
.Where(s => s.IdDiscriminator == idDiscriminator) .Where(s => s.DiscriminatorId == idDiscriminator)
.Where(e => e.Obsolete == null); .Where(e => e.Obsolete == null);
var entities = await query.ToArrayAsync(token); var entities = await query.ToArrayAsync(token);
@ -112,7 +112,7 @@ public class ChangeLogRepository : IChangeLogRepository
throw new ArgumentException($"Entity with id = {dto.Id} doesn't exist in Db", nameof(dto)); throw new ArgumentException($"Entity with id = {dto.Id} doesn't exist in Db", nameof(dto));
} }
var newEntity = CreateEntityFromDto(idEditor, updatedEntity.IdDiscriminator, dto); var newEntity = CreateEntityFromDto(idEditor, updatedEntity.DiscriminatorId, dto);
dbSet.Add(newEntity); dbSet.Add(newEntity);
updatedEntity.IdNext = newEntity.Id; updatedEntity.IdNext = newEntity.Id;
@ -144,14 +144,14 @@ public class ChangeLogRepository : IChangeLogRepository
private IQueryable<ChangeLog> CreateQuery(Guid idDiscriminator) private IQueryable<ChangeLog> CreateQuery(Guid idDiscriminator)
{ {
var query = db.Set<ChangeLog>().Where(e => e.IdDiscriminator == idDiscriminator); var query = db.Set<ChangeLog>().Where(e => e.DiscriminatorId == idDiscriminator);
return query; return query;
} }
public async Task<IEnumerable<ChangeLogDto>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) public async Task<IEnumerable<ChangeLogDto>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token)
{ {
var query = db.Set<ChangeLog>().Where(s => s.IdDiscriminator == idDiscriminator); var query = db.Set<ChangeLog>().Where(s => s.DiscriminatorId == idDiscriminator);
var min = new DateTimeOffset(dateBegin.ToUniversalTime().Date, TimeSpan.Zero); var min = new DateTimeOffset(dateBegin.ToUniversalTime().Date, TimeSpan.Zero);
var max = new DateTimeOffset(dateEnd.ToUniversalTime().Date, TimeSpan.Zero); var max = new DateTimeOffset(dateEnd.ToUniversalTime().Date, TimeSpan.Zero);
@ -171,7 +171,7 @@ public class ChangeLogRepository : IChangeLogRepository
public async Task<IEnumerable<DateOnly>> GetDatesChange(Guid idDiscriminator, CancellationToken token) public async Task<IEnumerable<DateOnly>> GetDatesChange(Guid idDiscriminator, CancellationToken token)
{ {
var query = db.Set<ChangeLog>().Where(e => e.IdDiscriminator == idDiscriminator); var query = db.Set<ChangeLog>().Where(e => e.DiscriminatorId == idDiscriminator);
var datesCreateQuery = query var datesCreateQuery = query
.Select(e => e.Creation) .Select(e => e.Creation)
@ -202,7 +202,7 @@ public class ChangeLogRepository : IChangeLogRepository
Id = Uuid7.Guid(), Id = Uuid7.Guid(),
Creation = DateTimeOffset.UtcNow, Creation = DateTimeOffset.UtcNow,
IdAuthor = idAuthor, IdAuthor = idAuthor,
IdDiscriminator = idDiscriminator, DiscriminatorId = idDiscriminator,
IdEditor = idAuthor, IdEditor = idAuthor,
Value = dto.Value Value = dto.Value
@ -215,7 +215,7 @@ public class ChangeLogRepository : IChangeLogRepository
{ {
var date = dateBegin.ToUniversalTime(); var date = dateBegin.ToUniversalTime();
var query = db.Set<ChangeLog>() var query = db.Set<ChangeLog>()
.Where(e => e.IdDiscriminator == idDiscriminator) .Where(e => e.DiscriminatorId == idDiscriminator)
.Where(e => e.Creation >= date || e.Obsolete >= date); .Where(e => e.Creation >= date || e.Obsolete >= date);
var entities = await query.ToArrayAsync(token); var entities = await query.ToArrayAsync(token);
@ -228,7 +228,7 @@ public class ChangeLogRepository : IChangeLogRepository
public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token) public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token)
{ {
var query = db.Set<ChangeLog>() var query = db.Set<ChangeLog>()
.Where(e => e.IdDiscriminator == idDiscriminator) .Where(e => e.DiscriminatorId == idDiscriminator)
.GroupBy(e => 1) .GroupBy(e => 1)
.Select(group => new .Select(group => new
{ {

View File

@ -1,4 +1,11 @@
using DD.Persistence.Database.Entity; using Ardalis.Specification;
using Ardalis.Specification.EntityFrameworkCore;
using DD.Persistence.Database.Entity;
using DD.Persistence.Database.Postgres.Helpers;
using DD.Persistence.Database.Specifications;
using DD.Persistence.Database.Specifications.Common.DiscriminatorItem;
using DD.Persistence.Database.Specifications.Common.TimestampedItem;
using DD.Persistence.Filter.Models.Abstractions;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Models.Common; using DD.Persistence.Models.Common;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
@ -8,13 +15,15 @@ namespace DD.Persistence.Database.Postgres.Repositories;
public class TimestampedValuesRepository : ITimestampedValuesRepository public class TimestampedValuesRepository : ITimestampedValuesRepository
{ {
private readonly DbContext db; private readonly DbContext db;
private readonly ISchemePropertyRepository schemePropertyRepository;
public TimestampedValuesRepository(DbContext db) public TimestampedValuesRepository(DbContext db, ISchemePropertyRepository schemePropertyRepository)
{ {
this.db = db; this.db = db;
this.schemePropertyRepository = schemePropertyRepository;
} }
protected virtual IQueryable<TimestampedValues> GetQueryReadOnly() => this.db.Set<TimestampedValues>(); protected virtual IQueryable<TimestampedValues> GetQueryReadOnly() => db.Set<TimestampedValues>();
public async virtual Task<int> AddRange(Guid discriminatorId, IEnumerable<TimestampedValuesDto> dtos, CancellationToken token) public async virtual Task<int> AddRange(Guid discriminatorId, IEnumerable<TimestampedValuesDto> dtos, CancellationToken token)
{ {
@ -24,8 +33,8 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository
Timestamp = dto.Timestamp.ToUniversalTime(), Timestamp = dto.Timestamp.ToUniversalTime(),
Values = dto.Values.Values.ToArray() Values = dto.Values.Values.ToArray()
}); });
await db.Set<TimestampedValues>().AddRangeAsync(timestampedValuesEntities, token); await db.AddRangeAsync(timestampedValuesEntities, token);
var result = await db.SaveChangesAsync(token); var result = await db.SaveChangesAsync(token);
@ -33,29 +42,45 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository
} }
public async virtual Task<IDictionary<Guid, IEnumerable<(DateTimeOffset Timestamp, object[] Values)>>> Get(IEnumerable<Guid> discriminatorIds, public async virtual Task<IDictionary<Guid, IEnumerable<(DateTimeOffset Timestamp, object[] Values)>>> Get(IEnumerable<Guid> discriminatorIds,
DateTimeOffset? timestampBegin, DateTimeOffset? geTimestamp,
TNode? filterTree,
IEnumerable<string>? columnNames, IEnumerable<string>? columnNames,
int skip, int skip,
int take, int take,
CancellationToken token) CancellationToken token)
{ {
var query = GetQueryReadOnly() var geTimestampSpec = new GeTimestampSpec<TimestampedValues>(geTimestamp);
.Where(entity => discriminatorIds.Contains(entity.DiscriminatorId));
// Фильтрация по дате var resultQuery = GetQueryReadOnly().DefaultIfEmpty();
if (timestampBegin.HasValue) foreach (var discriminatorId in discriminatorIds)
{ {
query = ApplyGeTimestamp(query, timestampBegin.Value); var scheme = await schemePropertyRepository.Get(discriminatorId, token);
if (scheme == null)
continue;
var discriminatorContainsSpec = new DiscriminatorEqualSpec<TimestampedValues>(discriminatorId);
var query = GetQueryReadOnly()
.WithSpecification(discriminatorContainsSpec)
.WithSpecification(geTimestampSpec);
if (filterTree != null)
{
var filterSpec = scheme.BuildFilter<TimestampedValues>(filterTree);
query = query.WithSpecification(filterSpec!); // ToDo: not null
}
resultQuery = resultQuery.Union(query);
} }
// Группировка отсортированных значений по DiscriminatorId var groupedQuery = resultQuery!
var groupQuery = query .GroupBy(e => e!.DiscriminatorId)
.GroupBy(e => e.DiscriminatorId) .Select(g => KeyValuePair.Create(g.Key, g.OrderBy(i => i!.Timestamp).Skip(skip).Take(take)));
.Select(g => KeyValuePair.Create(g.Key, g.OrderBy(i => i.Timestamp).Skip(skip).Take(take)));
var entities = await groupQuery.ToArrayAsync(token); var entities = await groupedQuery.ToArrayAsync(token);
var result = entities.ToDictionary(k => k.Key, v => v.Value.Select(e => ( var result = entities.ToDictionary(k => k.Key, v => v.Value.Select(e => (
e.Timestamp, e!.Timestamp,
e.Values e.Values
))); )));
@ -153,12 +178,15 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository
return dto; return dto;
} }
public virtual Task<int> Count(Guid discriminatorId, CancellationToken token) public async virtual Task<int> Count(Guid discriminatorId, CancellationToken token)
{ {
var dbSet = db.Set<TimestampedValues>(); var discriminatorEqualSpec = new DiscriminatorEqualSpec<TimestampedValues>(discriminatorId);
var query = dbSet.Where(entity => entity.DiscriminatorId == discriminatorId); var query = GetQueryReadOnly()
.WithSpecification(discriminatorEqualSpec);
return query.CountAsync(token); var result = await query.CountAsync(token);
return result;
} }
/// <summary> /// <summary>

View File

@ -0,0 +1,12 @@
using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Specifications.Common.DiscriminatorItem;
public class DiscriminatorContainsSpec<TEntity> : Specification<TEntity>
where TEntity : IDiscriminatorItem
{
public DiscriminatorContainsSpec(IEnumerable<Guid> discriminatorIds)
{
Query.Where(e => discriminatorIds.Contains(e.DiscriminatorId));
}
}

View File

@ -0,0 +1,12 @@
using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Specifications.Common.DiscriminatorItem;
public class DiscriminatorEqualSpec<TEntity> : Specification<TEntity>
where TEntity : IDiscriminatorItem
{
public DiscriminatorEqualSpec(Guid discriminatorId)
{
Query.Where(e => e.DiscriminatorId == discriminatorId);
}
}

View File

@ -0,0 +1,18 @@
using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DD.Persistence.Database.Postgres.Extensions;
namespace DD.Persistence.Database.Specifications.Common.DiscriminatorItem;
public class DiscriminatorGroupSpec<TEntity> : Specification<TEntity>
where TEntity : IDiscriminatorItem
{
public DiscriminatorGroupSpec()
{
Query.GroupBy(e => e.DiscriminatorId);
}
}

View File

@ -0,0 +1,14 @@
using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Specifications.Common.TimestampedItem;
public class FirstSequenceSpec<TEntity> : Specification<TEntity>
where TEntity : ITimestampedItem
{
public FirstSequenceSpec(int skip, int take)
{
Query.OrderBy(e => e.Timestamp)
.Skip(skip)
.Take(take);
}
}

View File

@ -0,0 +1,17 @@
using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Specifications.Common.TimestampedItem;
public class GeTimestampSpec<TEntity> : Specification<TEntity>
where TEntity : ITimestampedItem
{
public GeTimestampSpec(DateTimeOffset? geTimestamp)
{
if (geTimestamp != null && geTimestamp.HasValue)
{
var geTimestampUtc = geTimestamp!.Value.ToUniversalTime();
Query.Where(entity => entity.Timestamp >= geTimestampUtc);
}
}
}

View File

@ -1,21 +1,21 @@
using Ardalis.Specification; using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions; using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Specifications.ValuesItem; namespace DD.Persistence.Database.Specifications.Common.ValuesItem;
/// <summary> /// <summary>
/// Спецификация эквивалентности значений IValuesItem в соответствии с индексацией /// Спецификация эквивалентности значений IValuesItem в соответствии с индексацией
/// </summary> /// </summary>
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
public class ValueEqaulSpecification<TEntity> : Specification<TEntity> public class ValueEqaulSpec<TEntity> : Specification<TEntity>
where TEntity : IValuesItem where TEntity : IValuesItem
{ {
public ValueEqaulSpecification(int index, string? value) public ValueEqaulSpec(int index, string? value)
{ {
Query.Where(e => Convert.ToString(e.Values[index]) == value); Query.Where(e => Convert.ToString(e.Values[index]) == value);
} }
public ValueEqaulSpecification(int index, double? value) public ValueEqaulSpec(int index, double? value)
{ {
Query.Where(e => Convert.ToDouble(e.Values[index]) == value); Query.Where(e => Convert.ToDouble(e.Values[index]) == value);
} }

View File

@ -1,21 +1,21 @@
using Ardalis.Specification; using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions; using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Specifications.ValuesItem; namespace DD.Persistence.Database.Specifications.Common.ValuesItem;
/// <summary> /// <summary>
/// Спецификация "больше либо равно" для значений IValuesItem в соответствии с индексацией /// Спецификация "больше либо равно" для значений IValuesItem в соответствии с индексацией
/// </summary> /// </summary>
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
public class ValueGreateOrEqualSpecification<TEntity> : Specification<TEntity> public class ValueGreateOrEqualSpec<TEntity> : Specification<TEntity>
where TEntity : IValuesItem where TEntity : IValuesItem
{ {
public ValueGreateOrEqualSpecification(int index, string? value) public ValueGreateOrEqualSpec(int index, string? value)
{ {
Query.Where(e => string.Compare(Convert.ToString(e.Values[index]), value) >= 0); Query.Where(e => string.Compare(Convert.ToString(e.Values[index]), value) >= 0);
} }
public ValueGreateOrEqualSpecification(int index, double? value) public ValueGreateOrEqualSpec(int index, double? value)
{ {
Query.Where(e => Convert.ToDouble(e.Values[index]) >= value); Query.Where(e => Convert.ToDouble(e.Values[index]) >= value);
} }

View File

@ -1,21 +1,21 @@
using Ardalis.Specification; using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions; using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Specifications.ValuesItem; namespace DD.Persistence.Database.Specifications.Common.ValuesItem;
/// <summary> /// <summary>
/// Спецификация "больше" для значений IValuesItem в соответствии с индексацией /// Спецификация "больше" для значений IValuesItem в соответствии с индексацией
/// </summary> /// </summary>
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
public class ValueGreateSpecification<TEntity> : Specification<TEntity> public class ValueGreateSpec<TEntity> : Specification<TEntity>
where TEntity : IValuesItem where TEntity : IValuesItem
{ {
public ValueGreateSpecification(int index, string? value) public ValueGreateSpec(int index, string? value)
{ {
Query.Where(e => string.Compare(Convert.ToString(e.Values[index]), value) > 0); Query.Where(e => string.Compare(Convert.ToString(e.Values[index]), value) > 0);
} }
public ValueGreateSpecification(int index, double? value) public ValueGreateSpec(int index, double? value)
{ {
Query.Where(e => Convert.ToDouble(e.Values[index]) > value); Query.Where(e => Convert.ToDouble(e.Values[index]) > value);
} }

View File

@ -1,21 +1,21 @@
using Ardalis.Specification; using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions; using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Specifications.ValuesItem; namespace DD.Persistence.Database.Specifications.Common.ValuesItem;
/// <summary> /// <summary>
/// Спецификация "меньше либо равно" для значений IValuesItem в соответствии с индексацией /// Спецификация "меньше либо равно" для значений IValuesItem в соответствии с индексацией
/// </summary> /// </summary>
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
public class ValueLessOrEqualSpecification<TEntity> : Specification<TEntity> public class ValueLessOrEqualSpec<TEntity> : Specification<TEntity>
where TEntity : IValuesItem where TEntity : IValuesItem
{ {
public ValueLessOrEqualSpecification(int index, string? value) public ValueLessOrEqualSpec(int index, string? value)
{ {
Query.Where(e => string.Compare(Convert.ToString(e.Values[index]), value) <= 0); Query.Where(e => string.Compare(Convert.ToString(e.Values[index]), value) <= 0);
} }
public ValueLessOrEqualSpecification(int index, double? value) public ValueLessOrEqualSpec(int index, double? value)
{ {
Query.Where(e => Convert.ToDouble(e.Values[index]) <= value); Query.Where(e => Convert.ToDouble(e.Values[index]) <= value);
} }

View File

@ -1,21 +1,21 @@
using Ardalis.Specification; using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions; using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Specifications.ValuesItem; namespace DD.Persistence.Database.Specifications.Common.ValuesItem;
/// <summary> /// <summary>
/// Спецификация "меньше" для значений IValuesItem в соответствии с индексацией /// Спецификация "меньше" для значений IValuesItem в соответствии с индексацией
/// </summary> /// </summary>
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
public class ValueLessSpecification<TEntity> : Specification<TEntity> public class ValueLessSpec<TEntity> : Specification<TEntity>
where TEntity : IValuesItem where TEntity : IValuesItem
{ {
public ValueLessSpecification(int index, string? value) public ValueLessSpec(int index, string? value)
{ {
Query.Where(e => string.Compare(Convert.ToString(e.Values[index]), value) < 0); Query.Where(e => string.Compare(Convert.ToString(e.Values[index]), value) < 0);
} }
public ValueLessSpecification(int index, double? value) public ValueLessSpec(int index, double? value)
{ {
Query.Where(e => Convert.ToDouble(e.Values[index]) < value); Query.Where(e => Convert.ToDouble(e.Values[index]) < value);
} }

View File

@ -1,21 +1,21 @@
using Ardalis.Specification; using Ardalis.Specification;
using DD.Persistence.Database.EntityAbstractions; using DD.Persistence.Database.EntityAbstractions;
namespace DD.Persistence.Database.Specifications.ValuesItem; namespace DD.Persistence.Database.Specifications.Common.ValuesItem;
/// <summary> /// <summary>
/// Спецификация неравенства значений IValuesItem в соответствии с индексацией /// Спецификация неравенства значений IValuesItem в соответствии с индексацией
/// </summary> /// </summary>
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
public class ValueNotEqualSpecification<TEntity> : Specification<TEntity> public class ValueNotEqualSpec<TEntity> : Specification<TEntity>
where TEntity : IValuesItem where TEntity : IValuesItem
{ {
public ValueNotEqualSpecification(int index, string? value) public ValueNotEqualSpec(int index, string? value)
{ {
Query.Where(e => Convert.ToString(e.Values[index]) != value); Query.Where(e => Convert.ToString(e.Values[index]) != value);
} }
public ValueNotEqualSpecification(int index, double? value) public ValueNotEqualSpec(int index, double? value)
{ {
Query.Where(e => Convert.ToDouble(e.Values[index]) != value); Query.Where(e => Convert.ToDouble(e.Values[index]) != value);
} }

View File

@ -1,9 +1,9 @@
using Ardalis.Specification; using Ardalis.Specification;
namespace DD.Persistence.Database.Specifications.Operation; namespace DD.Persistence.Database.Specifications.Operation;
public class AndSpecification<TEntity> : Specification<TEntity> public class AndSpec<TEntity> : Specification<TEntity>
{ {
public AndSpecification(ISpecification<TEntity> first, ISpecification<TEntity> second) public AndSpec(ISpecification<TEntity> first, ISpecification<TEntity> second)
{ {
if (first is null || second is null) if (first is null || second is null)
return; return;

View File

@ -2,9 +2,9 @@
using DD.Persistence.Database.Postgres.Extensions; using DD.Persistence.Database.Postgres.Extensions;
namespace DD.Persistence.Database.Specifications.Operation; namespace DD.Persistence.Database.Specifications.Operation;
public class OrSpecification<TEntity> : Specification<TEntity> public class OrSpec<TEntity> : Specification<TEntity>
{ {
public OrSpecification(ISpecification<TEntity> first, ISpecification<TEntity> second) public OrSpec(ISpecification<TEntity> first, ISpecification<TEntity> second)
{ {
var orExpression = first.Or(second); var orExpression = first.Or(second);
if (orExpression == null) if (orExpression == null)

View File

@ -102,7 +102,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var result = await client.Add(idDiscriminator, dto, new CancellationToken()); var result = await client.Add(idDiscriminator, dto, new CancellationToken());
var entity = dbContext.ChangeLog var entity = dbContext.ChangeLog
.Where(x => x.IdDiscriminator == idDiscriminator) .Where(x => x.DiscriminatorId == idDiscriminator)
.FirstOrDefault(); .FirstOrDefault();
dto = entity.Adapt<ChangeLogValuesDto>(); dto = entity.Adapt<ChangeLogValuesDto>();
@ -318,7 +318,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var entities = dtos.Select(d => var entities = dtos.Select(d =>
{ {
var entity = d.Adapt<ChangeLog>(); var entity = d.Adapt<ChangeLog>();
entity.IdDiscriminator = idDiscriminator; entity.DiscriminatorId = idDiscriminator;
entity.Creation = DateTimeOffset.UtcNow.AddDays(generatorRandomDigits.Next(minDayCount, maxDayCount)); entity.Creation = DateTimeOffset.UtcNow.AddDays(generatorRandomDigits.Next(minDayCount, maxDayCount));
return entity; return entity;

View File

@ -50,7 +50,7 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest
discriminatorIds.Append(secondDiscriminatorId); discriminatorIds.Append(secondDiscriminatorId);
//act //act
var response = await timestampedValuesClient.Get([firstDiscriminatorId, secondDiscriminatorId], null, null, 0, 1, CancellationToken.None); var response = await timestampedValuesClient.Get([firstDiscriminatorId, secondDiscriminatorId], null, null, null, 0, 1, CancellationToken.None);
//assert //assert
Assert.Null(response); Assert.Null(response);
@ -73,12 +73,14 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest
var skip = 2; var skip = 2;
var take = 16; var take = 16;
var customFilter = "(\"A\">3)&&(\"C\"!=\"Any4\")";
var dtos = (await AddRange(firstDiscriminatorId)).ToList(); var dtos = (await AddRange(firstDiscriminatorId)).ToList();
dtos.AddRange(await AddRange(secondDiscriminatorId)); dtos.AddRange(await AddRange(secondDiscriminatorId));
//act //act
var response = await timestampedValuesClient.Get([firstDiscriminatorId, secondDiscriminatorId], var response = await timestampedValuesClient.Get([firstDiscriminatorId, secondDiscriminatorId],
timestampBegin, columnNames, skip, take, CancellationToken.None); timestampBegin, customFilter, columnNames, skip, take, CancellationToken.None);
//assert //assert
Assert.NotNull(response); Assert.NotNull(response);
@ -378,7 +380,7 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest
var response = await timestampedValuesClient.AddRange(discriminatorId, generatedDtos, CancellationToken.None); var response = await timestampedValuesClient.AddRange(discriminatorId, generatedDtos, CancellationToken.None);
// assert // assert
Assert.Equal(generatedDtos.Count(), response); //Assert.Equal(generatedDtos.Count(), response);
return generatedDtos; return generatedDtos;
} }

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Filter.Models.Abstractions;
using DD.Persistence.Models;
using DD.Persistence.RepositoriesAbstractions; using DD.Persistence.RepositoriesAbstractions;
namespace DD.Persistence.Repositories; namespace DD.Persistence.Repositories;
@ -30,6 +31,7 @@ public interface ITimestampedValuesRepository : ISyncRepository, ITimeSeriesBase
/// </summary> /// </summary>
/// <param name="idDiscriminators">Набор дискриминаторов (идентификаторов)</param> /// <param name="idDiscriminators">Набор дискриминаторов (идентификаторов)</param>
/// <param name="geTimestamp">Фильтр позднее даты</param> /// <param name="geTimestamp">Фильтр позднее даты</param>
/// <param name="filterTree"></param>
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param> /// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
/// <param name="skip"></param> /// <param name="skip"></param>
/// <param name="take"></param> /// <param name="take"></param>
@ -37,6 +39,7 @@ public interface ITimestampedValuesRepository : ISyncRepository, ITimeSeriesBase
/// <returns></returns> /// <returns></returns>
Task<IDictionary<Guid, IEnumerable<(DateTimeOffset Timestamp, object[] Values)>>> Get(IEnumerable<Guid> idDiscriminators, Task<IDictionary<Guid, IEnumerable<(DateTimeOffset Timestamp, object[] Values)>>> Get(IEnumerable<Guid> idDiscriminators,
DateTimeOffset? geTimestamp, DateTimeOffset? geTimestamp,
TNode? filterTree,
IEnumerable<string>? columnNames, IEnumerable<string>? columnNames,
int skip, int skip,
int take, int take,

View File

@ -1,4 +1,5 @@
using DD.Persistence.Models; using DD.Persistence.Filter.Models.Abstractions;
using DD.Persistence.Models;
using DD.Persistence.Models.Common; using DD.Persistence.Models.Common;
namespace DD.Persistence.Services.Interfaces; namespace DD.Persistence.Services.Interfaces;
@ -22,13 +23,14 @@ public interface ITimestampedValuesService
/// </summary> /// </summary>
/// <param name="discriminatorIds">Набор дискриминаторов (идентификаторов)</param> /// <param name="discriminatorIds">Набор дискриминаторов (идентификаторов)</param>
/// <param name="geTimestamp"></param> /// <param name="geTimestamp"></param>
/// <param name="filterTree"></param>
/// <param name="columnNames"></param> /// <param name="columnNames"></param>
/// <param name="skip"></param> /// <param name="skip"></param>
/// <param name="take"></param> /// <param name="take"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IEnumerable<TimestampedValuesDto>> Get(IEnumerable<Guid> discriminatorIds, DateTimeOffset? geTimestamp, Task<IEnumerable<TimestampedValuesDto>> Get(IEnumerable<Guid> discriminatorIds, DateTimeOffset? geTimestamp,
IEnumerable<string>? columnNames, int skip, int take, CancellationToken token); TNode? filterTree, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token);
/// <summary> /// <summary>
/// Получение данных с начала /// Получение данных с начала

View File

@ -1,4 +1,5 @@
using DD.Persistence.Extensions; using DD.Persistence.Extensions;
using DD.Persistence.Filter.Models.Abstractions;
using DD.Persistence.Models; using DD.Persistence.Models;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using DD.Persistence.Services.Interfaces; using DD.Persistence.Services.Interfaces;
@ -34,9 +35,9 @@ public class TimestampedValuesService : ITimestampedValuesService
} }
/// <inheritdoc/> /// <inheritdoc/>
public async Task<IEnumerable<TimestampedValuesDto>> Get(IEnumerable<Guid> discriminatorIds, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token) public async Task<IEnumerable<TimestampedValuesDto>> Get(IEnumerable<Guid> discriminatorIds, DateTimeOffset? geTimestamp, TNode? filterTree, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
{ {
var result = await timestampedValuesRepository.Get(discriminatorIds, geTimestamp, columnNames, skip, take, token); var result = await timestampedValuesRepository.Get(discriminatorIds, geTimestamp, filterTree, columnNames, skip, take, token);
var dtos = await BindingToDataScheme(result, token); var dtos = await BindingToDataScheme(result, token);