From a3605253d6a0f6d8bf087507ee97e1cb9ec23fee Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Thu, 23 Jan 2025 17:33:01 +0500 Subject: [PATCH 1/8] =?UTF-8?q?=D0=9C=D0=B5=D1=82=D0=BE=D0=B4=20Get=20?= =?UTF-8?q?=D1=81=20=D0=BC=D0=B0=D1=81=D1=81=D0=B8=D0=B2=D0=BE=D0=BC=20?= =?UTF-8?q?=D0=B4=D0=B8=D1=81=D0=BA=D1=80=D0=B8=D0=BC=D0=B8=D0=BD=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimestampedValuesController.cs | 59 +++++++++++------ .../Interfaces/ITimestampedValuesClient.cs | 23 ++++++- .../Refit/IRefitTimestampedValuesClient.cs | 36 ++++++++--- .../Clients/TimestampedValuesClient.cs | 18 ++++-- .../TimestampedValuesControllerTest.cs | 64 +++++++++++++++++++ .../TimestampedValuesRepository.cs | 38 ++++++++++- .../Extensions/IEnumerableExtensions.cs | 3 + .../ITimestampedValuesRepository.cs | 9 ++- .../Interfaces/ITimestampedValuesService.cs | 16 ++++- .../Services/TimestampedValuesService.cs | 19 ++++++ 10 files changed, 245 insertions(+), 40 deletions(-) diff --git a/DD.Persistence.API/Controllers/TimestampedValuesController.cs b/DD.Persistence.API/Controllers/TimestampedValuesController.cs index abc1114..df8127a 100644 --- a/DD.Persistence.API/Controllers/TimestampedValuesController.cs +++ b/DD.Persistence.API/Controllers/TimestampedValuesController.cs @@ -12,14 +12,14 @@ namespace DD.Persistence.API.Controllers; /// [ApiController] [Authorize] -[Route("api/[controller]/{discriminatorId}")] +[Route("api/[controller]")] public class TimestampedValuesController : ControllerBase { - private readonly ITimestampedValuesService timestampedValuesRepository; + private readonly ITimestampedValuesService timestampedValuesService; - public TimestampedValuesController(ITimestampedValuesService repository) + public TimestampedValuesController(ITimestampedValuesService service) { - this.timestampedValuesRepository = repository; + this.timestampedValuesService = service; } /// @@ -29,11 +29,11 @@ public class TimestampedValuesController : ControllerBase /// Дискриминатор (идентификатор) набора /// /// - [HttpPost] + [HttpPost("{discriminatorId}")] [ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)] public async Task AddRange([FromRoute] Guid discriminatorId, [FromBody] IEnumerable dtos, CancellationToken token) { - var result = await timestampedValuesRepository.AddRange(discriminatorId, dtos, token); + var result = await timestampedValuesService.AddRange(discriminatorId, dtos, token); return CreatedAtAction(nameof(AddRange), result); } @@ -47,12 +47,31 @@ public class TimestampedValuesController : ControllerBase /// /// /// - [HttpGet] + [HttpGet("{discriminatorId}")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.NoContent)] public async Task>> Get([FromRoute] Guid discriminatorId, DateTimeOffset? timestampBegin, [FromQuery] string[]? columnNames, int skip, int take, CancellationToken token) { - var result = await timestampedValuesRepository.Get(discriminatorId, timestampBegin, columnNames, skip, take, token); + var result = await timestampedValuesService.Get(discriminatorId, timestampBegin, columnNames, skip, take, token); + + return result.Any() ? Ok(result) : NoContent(); + } + + /// + /// Получение данных с фильтрацией для нескольких систем. Значение фильтра null - отключен + /// + /// Набор дискриминаторов (идентификаторов) + /// Фильтр позднее даты + /// Фильтр свойств набора + /// + /// + /// + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NoContent)] + public async Task>> Get([FromQuery] IEnumerable discriminatorIds, DateTimeOffset? timestampBegin, [FromQuery] string[]? columnNames, int skip, int take, CancellationToken token) + { + var result = await timestampedValuesService.Get(discriminatorIds, timestampBegin, columnNames, skip, take, token); return result.Any() ? Ok(result) : NoContent(); } @@ -63,12 +82,12 @@ public class TimestampedValuesController : ControllerBase /// Дискриминатор (идентификатор) набора /// Фильтр позднее даты /// - [HttpGet("gtdate")] + [HttpGet("{discriminatorId}/gtdate")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.NoContent)] public async Task>> GetGtDate([FromRoute] Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token) { - var result = await timestampedValuesRepository.GetGtDate(discriminatorId, timestampBegin, token); + var result = await timestampedValuesService.GetGtDate(discriminatorId, timestampBegin, token); return result.Any() ? Ok(result) : NoContent(); } @@ -79,12 +98,12 @@ public class TimestampedValuesController : ControllerBase /// Дискриминатор (идентификатор) набора /// /// - [HttpGet("first")] + [HttpGet("{discriminatorId}/first")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.NoContent)] public async Task>> GetFirst([FromRoute] Guid discriminatorId, int take, CancellationToken token) { - var result = await timestampedValuesRepository.GetFirst(discriminatorId, take, token); + var result = await timestampedValuesService.GetFirst(discriminatorId, take, token); return result.Any() ? Ok(result) : NoContent(); } @@ -95,12 +114,12 @@ public class TimestampedValuesController : ControllerBase /// Дискриминатор (идентификатор) набора /// /// - [HttpGet("last")] + [HttpGet("{discriminatorId}/last")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.NoContent)] public async Task>> GetLast([FromRoute] Guid discriminatorId, int take, CancellationToken token) { - var result = await timestampedValuesRepository.GetLast(discriminatorId, take, token); + var result = await timestampedValuesService.GetLast(discriminatorId, take, token); return result.Any() ? Ok(result) : NoContent(); } @@ -113,12 +132,12 @@ public class TimestampedValuesController : ControllerBase /// /// /// - [HttpGet("resampled")] + [HttpGet("{discriminatorId}/resampled")] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.NoContent)] public async Task>> GetResampledData([FromRoute] Guid discriminatorId, DateTimeOffset timestampBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default) { - var result = await timestampedValuesRepository.GetResampledData(discriminatorId, timestampBegin, intervalSec, approxPointsCount, token); + var result = await timestampedValuesService.GetResampledData(discriminatorId, timestampBegin, intervalSec, approxPointsCount, token); return result.Any() ? Ok(result) : NoContent(); } @@ -128,10 +147,10 @@ public class TimestampedValuesController : ControllerBase /// /// Дискриминатор (идентификатор) набора /// - [HttpGet("count")] + [HttpGet("{discriminatorId}/count")] public async Task> Count([FromRoute] Guid discriminatorId, CancellationToken token) { - var result = await timestampedValuesRepository.Count(discriminatorId, token); + var result = await timestampedValuesService.Count(discriminatorId, token); return Ok(result); } @@ -141,10 +160,10 @@ public class TimestampedValuesController : ControllerBase /// /// /// - [HttpGet("datesRange")] + [HttpGet("{discriminatorId}/datesRange")] public async Task> GetDatesRange([FromRoute] Guid discriminatorId, CancellationToken token) { - var result = await timestampedValuesRepository.GetDatesRange(discriminatorId, token); + var result = await timestampedValuesService.GetDatesRange(discriminatorId, token); return Ok(result); } diff --git a/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs b/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs index b0ea180..1a2ac57 100644 --- a/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs +++ b/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs @@ -28,7 +28,28 @@ public interface ITimestampedValuesClient : IDisposable /// /// /// - Task> Get(Guid discriminatorId, DateTimeOffset? timestampBegin, IEnumerable? columnNames, int skip, int take, CancellationToken token); + Task> Get(Guid discriminatorId, + DateTimeOffset? timestampBegin, + IEnumerable? columnNames, + int skip, + int take, + CancellationToken token); + + /// + /// Получить данные с фильтрацией для нескольких систем. Значение фильтра null - отключен + /// + /// Набор дискриминаторов (идентификаторов) + /// Фильтр позднее даты + /// Фильтр свойств набора + /// + /// + /// + Task> Get(IEnumerable discriminatorIds, + DateTimeOffset? timestampBegin, + IEnumerable? columnNames, + int skip, + int take, + CancellationToken token); /// /// Получить данные, начиная с заданной отметки времени diff --git a/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedValuesClient.cs b/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedValuesClient.cs index bd94136..e8457ad 100644 --- a/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedValuesClient.cs +++ b/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedValuesClient.cs @@ -9,53 +9,69 @@ namespace DD.Persistence.Client.Clients.Interfaces.Refit; /// public interface IRefitTimestampedValuesClient : IRefitClient, IDisposable { - private const string baseUrl = "/api/TimestampedValues/{discriminatorId}"; + private const string baseUrl = "/api/TimestampedValues"; /// /// Записать новые данные /// - [Post(baseUrl)] + [Post($"{baseUrl}/{{discriminatorId}}")] Task> AddRange(Guid discriminatorId, IEnumerable dtos, CancellationToken token); + /// + /// Получение данных с фильтрацией для нескольких систем + /// + [Get($"{baseUrl}/{{discriminatorId}}")] + Task>> Get(Guid discriminatorId, + DateTimeOffset? timestampBegin, + [Query(CollectionFormat.Multi)] IEnumerable? columnNames, + int skip, + int take, + CancellationToken token); + /// /// Получение данных с фильтрацией /// - [Get(baseUrl)] - Task>> Get(Guid discriminatorId, DateTimeOffset? timestampBegin, [Query(CollectionFormat.Multi)] IEnumerable? columnNames, int skip, int take, CancellationToken token); + [Get($"{baseUrl}")] + Task>> Get([Query(CollectionFormat.Multi)] IEnumerable discriminatorIds, + DateTimeOffset? timestampBegin, + [Query(CollectionFormat.Multi)] IEnumerable? columnNames, + int skip, + int take, + CancellationToken token); /// /// Получить данные, начиная с заданной отметки времени /// - [Get($"{baseUrl}/gtdate")] + [Get($"{baseUrl}/{{discriminatorId}}/gtdate")] Task>> GetGtDate(Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token); /// /// Получить данные c начала /// - [Get($"{baseUrl}/first")] + [Get($"{baseUrl}/{{discriminatorId}}/first")] Task>> GetFirst(Guid discriminatorId, int take, CancellationToken token); /// /// Получить данные c конца /// - [Get($"{baseUrl}/last")] + [Get($"{baseUrl}/{{discriminatorId}}/last")] Task>> GetLast(Guid discriminatorId, int take, CancellationToken token); /// /// Получить список объектов с прореживанием, удовлетворяющий диапазону временных отметок /// - [Get($"{baseUrl}/resampled")] + [Get($"{baseUrl}/{{discriminatorId}}/resampled")] Task>> GetResampledData(Guid discriminatorId, DateTimeOffset timestampBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default); /// /// Получить количество записей по указанному набору в БД. Для пагинации /// - [Get($"{baseUrl}/count")] + [Get($"{baseUrl}/{{discriminatorId}}/count")] Task> Count(Guid discriminatorId, CancellationToken token); /// /// Получить диапазон дат, в пределах которых хранятся даные /// - [Get($"{baseUrl}/datesRange")] + [Get($"{baseUrl}/{{discriminatorId}}/datesRange")] Task> GetDatesRange(Guid discriminatorId, CancellationToken token); } diff --git a/DD.Persistence.Client/Clients/TimestampedValuesClient.cs b/DD.Persistence.Client/Clients/TimestampedValuesClient.cs index bafead6..e5b35a3 100644 --- a/DD.Persistence.Client/Clients/TimestampedValuesClient.cs +++ b/DD.Persistence.Client/Clients/TimestampedValuesClient.cs @@ -36,7 +36,15 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient { var result = await ExecuteGetResponse( async () => await refitTimestampedSetClient.Get(discriminatorId, geTimestamp, columnNames, skip, take, token), token); - return result; + return result!; + } + + /// + public async Task> Get(IEnumerable discriminatorIds, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) + { + var result = await ExecuteGetResponse( + async () => await refitTimestampedSetClient.Get(discriminatorIds, geTimestamp, columnNames, skip, take, token), token); + return result!; } /// @@ -45,7 +53,7 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient var result = await ExecuteGetResponse( async () => await refitTimestampedSetClient.GetGtDate(discriminatorId, timestampBegin, token), token); - return result; + return result!; } /// @@ -54,7 +62,7 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient var result = await ExecuteGetResponse( async () => await refitTimestampedSetClient.GetFirst(discriminatorId, take, token), token); - return result; + return result!; } /// @@ -63,7 +71,7 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient var result = await ExecuteGetResponse( async () => await refitTimestampedSetClient.GetLast(discriminatorId, take, token), token); - return result; + return result!; } /// @@ -72,7 +80,7 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient var result = await ExecuteGetResponse( async () => await refitTimestampedSetClient.GetResampledData(discriminatorId, dateBegin, intervalSec, approxPointsCount, token), token); - return result; + return result!; } /// diff --git a/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs b/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs index 71a49d5..10dbd76 100644 --- a/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs +++ b/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs @@ -3,6 +3,7 @@ using DD.Persistence.Client.Clients; using DD.Persistence.Client.Clients.Interfaces; using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Database.Entity; +using DD.Persistence.Extensions; using DD.Persistence.Models; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; @@ -92,6 +93,69 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest Assert.Equal(expectedValueKind, actualValueKind); } + [Fact] + public async Task GetWithManyDiscriminators_returns_success() + { + //arrange + Cleanup(); + + var firstDiscriminatorId = Guid.NewGuid(); + discriminatorIds.Append(firstDiscriminatorId); + + var secondDiscriminatorId = Guid.NewGuid(); + discriminatorIds.Append(secondDiscriminatorId); + + //act + var response = await timestampedValuesClient.Get([firstDiscriminatorId, secondDiscriminatorId], null, null, 0, 1, CancellationToken.None); + + //assert + Assert.Null(response); + } + + [Fact] + public async Task GetWithManyDiscriminators_AfterSave_returns_success() + { + //arrange + Cleanup(); + + var firstDiscriminatorId = Guid.NewGuid(); + discriminatorIds.Append(firstDiscriminatorId); + + var secondDiscriminatorId = Guid.NewGuid(); + discriminatorIds.Append(secondDiscriminatorId); + + var timestampBegin = DateTimeOffset.UtcNow.AddDays(-1); + var columnNames = new List() { "A", "C" }; + var skip = 2; + var take = 16; + + var dtos = (await AddRange(firstDiscriminatorId)).ToList(); + dtos.AddRange(await AddRange(secondDiscriminatorId)); + + //act + var response = await timestampedValuesClient.Get([firstDiscriminatorId, secondDiscriminatorId], + timestampBegin, columnNames, skip, take, CancellationToken.None); + + //assert + Assert.NotNull(response); + Assert.NotEmpty(response); + + var actualCount = response.Count(); + Assert.Equal(take, actualCount); + + var actualColumnNames = response.SelectMany(e => e.Values.Keys).Distinct().ToList(); + Assert.Equal(columnNames, actualColumnNames); + + var expectedValueKind = JsonValueKind.Number; + var actualValueKind = ((JsonElement)response.First().Values["A"]).ValueKind; + Assert.Equal(expectedValueKind, actualValueKind); + + expectedValueKind = JsonValueKind.String; + actualValueKind = ((JsonElement)response.First().Values["C"]).ValueKind; + Assert.Equal(expectedValueKind, actualValueKind); + } + + [Fact] public async Task GetGtDate_returns_success() { diff --git a/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs b/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs index 204b1a2..1a3ea47 100644 --- a/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs +++ b/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs @@ -3,6 +3,7 @@ using DD.Persistence.Models; using DD.Persistence.Models.Common; using DD.Persistence.Repositories; using Microsoft.EntityFrameworkCore; +using System.Linq; namespace DD.Persistence.Repository.Repositories; public class TimestampedValuesRepository : ITimestampedValuesRepository @@ -37,7 +38,12 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository return result; } - public async virtual Task>> Get(Guid discriminatorId, DateTimeOffset? timestampBegin, IEnumerable? columnNames, int skip, int take, CancellationToken token) + public async virtual Task>> Get(Guid discriminatorId, + DateTimeOffset? timestampBegin, + IEnumerable? columnNames, + int skip, + int take, + CancellationToken token) { var query = GetQueryReadOnly() .Where(entity => entity.DiscriminatorId == discriminatorId); @@ -62,6 +68,36 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository return result; } + public async virtual Task>> Get(IEnumerable discriminatorIds, + DateTimeOffset? timestampBegin, + IEnumerable? columnNames, + int skip, + int take, + CancellationToken token) + { + var query = GetQueryReadOnly() + .Where(entity => discriminatorIds.Contains(entity.DiscriminatorId)); + + // Фильтрация по дате + if (timestampBegin.HasValue) + { + query = ApplyGeTimestamp(query, timestampBegin.Value); + } + + query = query + .OrderBy(item => item.Timestamp) + .Skip(skip) + .Take(take); + var entities = await query.ToArrayAsync(token); + + var result = entities.Select(e => Tuple.Create( + e.Timestamp, + e.Values + )); + + return result; + } + public async virtual Task>> GetFirst(Guid discriminatorId, int takeCount, CancellationToken token) { var query = GetQueryReadOnly() diff --git a/DD.Persistence/Extensions/IEnumerableExtensions.cs b/DD.Persistence/Extensions/IEnumerableExtensions.cs index 702a08b..33fbb1a 100644 --- a/DD.Persistence/Extensions/IEnumerableExtensions.cs +++ b/DD.Persistence/Extensions/IEnumerableExtensions.cs @@ -1,7 +1,9 @@ namespace DD.Persistence.Extensions; +/// public static class IEnumerableExtensions { + /// public static void ForEach(this IEnumerable source, Action action) { if (source == null) @@ -15,6 +17,7 @@ public static class IEnumerableExtensions } } + /// public static bool IsNullOrEmpty(this IEnumerable? enumerable) { if (enumerable == null) diff --git a/DD.Persistence/Repositories/ITimestampedValuesRepository.cs b/DD.Persistence/Repositories/ITimestampedValuesRepository.cs index 6bd2866..c4db6ef 100644 --- a/DD.Persistence/Repositories/ITimestampedValuesRepository.cs +++ b/DD.Persistence/Repositories/ITimestampedValuesRepository.cs @@ -7,7 +7,7 @@ namespace DD.Persistence.Repositories; /// Репозиторий для работы с временными данными /// public interface ITimestampedValuesRepository : ISyncRepository, ITimeSeriesBaseRepository -{ +{ /// /// Добавление записей /// @@ -35,7 +35,12 @@ public interface ITimestampedValuesRepository : ISyncRepository, ITimeSeriesBase /// /// /// - Task>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token); + Task>> Get(Guid idDiscriminator, + DateTimeOffset? geTimestamp, + IEnumerable? columnNames, + int skip, + int take, + CancellationToken token); /// /// Получение данных с начала diff --git a/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs b/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs index 8e6d606..0d075d6 100644 --- a/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs +++ b/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs @@ -35,7 +35,21 @@ public interface ITimestampedValuesService /// /// /// - Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token); + Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, + IEnumerable? columnNames, int skip, int take, CancellationToken token); + + /// + /// Получение данных с фильтрацией для нескольких систем. Значение фильтра null - отключен + /// + /// Набор дискриминаторов (идентификаторов) + /// + /// + /// + /// + /// + /// + Task> Get(IEnumerable discriminatorIds, DateTimeOffset? geTimestamp, + IEnumerable? columnNames, int skip, int take, CancellationToken token); /// /// Получение данных с начала diff --git a/DD.Persistence/Services/TimestampedValuesService.cs b/DD.Persistence/Services/TimestampedValuesService.cs index 81a8fd3..31bb6b6 100644 --- a/DD.Persistence/Services/TimestampedValuesService.cs +++ b/DD.Persistence/Services/TimestampedValuesService.cs @@ -49,6 +49,25 @@ public class TimestampedValuesService : ITimestampedValuesService return dtos; } + /// + public async Task> Get(IEnumerable discriminatorIds, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) + { + var result = await timestampedValuesRepository.Get(discriminatorIds, geTimestamp, columnNames, skip, take, token); + + List dtos = []; + discriminatorIds.ForEach(async discriminatorId => { + var materializeDtos = await Materialize(discriminatorId, result, token); + dtos.AddRange(materializeDtos); + }); + + if (!columnNames.IsNullOrEmpty()) + { + dtos = ReduceSetColumnsByNames(dtos, columnNames!).ToList(); + } + + return dtos; + } + /// public async Task> GetFirst(Guid discriminatorId, int takeCount, CancellationToken token) { From 8fd16512f332fb867d43f1d1d64435a03cddbcee Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Fri, 24 Jan 2025 15:40:14 +0500 Subject: [PATCH 2/8] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B0=20Get=20?= =?UTF-8?q?=D0=BA=20TimestampedValues?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimestampedValuesController.cs | 28 +---- .../Interfaces/ITimestampedValuesClient.cs | 29 ----- .../Refit/IRefitTimestampedValuesClient.cs | 11 -- .../Clients/TimestampedValuesClient.cs | 17 --- .../TimestampedValuesControllerTest.cs | 112 +++++++++--------- .../TimestampedValuesRepository.cs | 61 +++------- .../ITimestampedValuesRepository.cs | 8 +- .../ISyncRepository.cs | 2 +- .../ITimeSeriesBaseRepository.cs | 2 +- .../Interfaces/ITimestampedValuesService.cs | 13 -- .../Services/TimestampedValuesService.cs | 86 ++++++-------- 11 files changed, 120 insertions(+), 249 deletions(-) diff --git a/DD.Persistence.API/Controllers/TimestampedValuesController.cs b/DD.Persistence.API/Controllers/TimestampedValuesController.cs index df8127a..bb4934c 100644 --- a/DD.Persistence.API/Controllers/TimestampedValuesController.cs +++ b/DD.Persistence.API/Controllers/TimestampedValuesController.cs @@ -1,7 +1,6 @@ using DD.Persistence.Models; using DD.Persistence.Models.Common; using DD.Persistence.Services.Interfaces; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Net; @@ -11,15 +10,15 @@ namespace DD.Persistence.API.Controllers; /// Хранение наборов данных с отметкой времени. /// [ApiController] -[Authorize] +//[Authorize] [Route("api/[controller]")] public class TimestampedValuesController : ControllerBase { private readonly ITimestampedValuesService timestampedValuesService; - public TimestampedValuesController(ITimestampedValuesService service) + public TimestampedValuesController(ITimestampedValuesService repository) { - this.timestampedValuesService = service; + this.timestampedValuesService = repository; } /// @@ -41,26 +40,7 @@ public class TimestampedValuesController : ControllerBase /// /// Получение данных с фильтрацией. Значение фильтра null - отключен /// - /// Дискриминатор (идентификатор) набора - /// Фильтр позднее даты - /// Фильтр свойств набора - /// - /// - /// - [HttpGet("{discriminatorId}")] - [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.NoContent)] - public async Task>> Get([FromRoute] Guid discriminatorId, DateTimeOffset? timestampBegin, [FromQuery] string[]? columnNames, int skip, int take, CancellationToken token) - { - var result = await timestampedValuesService.Get(discriminatorId, timestampBegin, columnNames, skip, take, token); - - return result.Any() ? Ok(result) : NoContent(); - } - - /// - /// Получение данных с фильтрацией для нескольких систем. Значение фильтра null - отключен - /// - /// Набор дискриминаторов (идентификаторов) + /// Набор дискриминаторов /// Фильтр позднее даты /// Фильтр свойств набора /// diff --git a/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs b/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs index 1a2ac57..e7d7be6 100644 --- a/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs +++ b/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs @@ -19,22 +19,6 @@ public interface ITimestampedValuesClient : IDisposable /// Task AddRange(Guid discriminatorId, IEnumerable dtos, CancellationToken token); - /// - /// Получить данные с фильтрацией. Значение фильтра null - отключен - /// - /// Дискриминатор (идентификатор) набора - /// Фильтр позднее даты - /// Фильтр свойств набора - /// - /// - /// - Task> Get(Guid discriminatorId, - DateTimeOffset? timestampBegin, - IEnumerable? columnNames, - int skip, - int take, - CancellationToken token); - /// /// Получить данные с фильтрацией для нескольких систем. Значение фильтра null - отключен /// @@ -99,19 +83,6 @@ public interface ITimestampedValuesClient : IDisposable /// Task GetDatesRange(Guid discriminatorId, CancellationToken token); - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token); - /// /// /// diff --git a/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedValuesClient.cs b/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedValuesClient.cs index e8457ad..7c56f12 100644 --- a/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedValuesClient.cs +++ b/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitTimestampedValuesClient.cs @@ -17,17 +17,6 @@ public interface IRefitTimestampedValuesClient : IRefitClient, IDisposable [Post($"{baseUrl}/{{discriminatorId}}")] Task> AddRange(Guid discriminatorId, IEnumerable dtos, CancellationToken token); - /// - /// Получение данных с фильтрацией для нескольких систем - /// - [Get($"{baseUrl}/{{discriminatorId}}")] - Task>> Get(Guid discriminatorId, - DateTimeOffset? timestampBegin, - [Query(CollectionFormat.Multi)] IEnumerable? columnNames, - int skip, - int take, - CancellationToken token); - /// /// Получение данных с фильтрацией /// diff --git a/DD.Persistence.Client/Clients/TimestampedValuesClient.cs b/DD.Persistence.Client/Clients/TimestampedValuesClient.cs index e5b35a3..4c77b20 100644 --- a/DD.Persistence.Client/Clients/TimestampedValuesClient.cs +++ b/DD.Persistence.Client/Clients/TimestampedValuesClient.cs @@ -31,14 +31,6 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient return result; } - /// - public async Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) - { - var result = await ExecuteGetResponse( - async () => await refitTimestampedSetClient.Get(discriminatorId, geTimestamp, columnNames, skip, take, token), token); - return result!; - } - /// public async Task> Get(IEnumerable discriminatorIds, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) { @@ -101,15 +93,6 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient return result; } - /// - public async Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) - { - var data = await Get(idDiscriminator, geTimestamp, columnNames, skip, take, token); - var mapper = GetMapper(idDiscriminator); - - return data.Select(mapper.DeserializeTimeStampedData); - } - /// public async Task> GetLast(Guid idDiscriminator, int take, CancellationToken token) { diff --git a/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs b/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs index 10dbd76..3131ec5 100644 --- a/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs +++ b/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs @@ -38,67 +38,67 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest await AddRange(discriminatorId); } + //[Fact] + //public async Task Get_returns_success() + //{ + // //arrange + // Cleanup(); + + // var discriminatorId = Guid.NewGuid(); + // discriminatorIds.Append(discriminatorId); + + // //act + // var response = await timestampedValuesClient.Get(discriminatorId, null, null, 0, 1, CancellationToken.None); + + // //assert + // Assert.Null(response); + //} + + //[Fact] + + //public async Task Get_AfterSave_returns_success() + //{ + // //arrange + // Cleanup(); + + // var discriminatorId = Guid.NewGuid(); + // discriminatorIds.Append(discriminatorId); + + // var timestampBegin = DateTimeOffset.UtcNow.AddDays(-1); + // var columnNames = new List() { "A", "C" }; + // var skip = 5; + // var take = 5; + + // var dtos = await AddRange(discriminatorId); + + // //act + // var response = await timestampedValuesClient.Get(discriminatorId, timestampBegin, columnNames, skip, take, CancellationToken.None); + + // //assert + // Assert.NotNull(response); + // Assert.NotEmpty(response); + + // var actualCount = response.Count(); + // Assert.Equal(take, actualCount); + + // var actualColumnNames = response.SelectMany(e => e.Values.Keys).Distinct().ToList(); + // Assert.Equal(columnNames, actualColumnNames); + + // var expectedValueKind = JsonValueKind.Number; + // var actualValueKind = ((JsonElement) response.First().Values["A"]).ValueKind; + // Assert.Equal(expectedValueKind, actualValueKind); + + // expectedValueKind = JsonValueKind.String; + // actualValueKind = ((JsonElement)response.First().Values["C"]).ValueKind; + // Assert.Equal(expectedValueKind, actualValueKind); + //} + [Fact] public async Task Get_returns_success() { //arrange Cleanup(); - var discriminatorId = Guid.NewGuid(); - discriminatorIds.Append(discriminatorId); - - //act - var response = await timestampedValuesClient.Get(discriminatorId, null, null, 0, 1, CancellationToken.None); - - //assert - Assert.Null(response); - } - - [Fact] - - public async Task Get_AfterSave_returns_success() - { - //arrange - Cleanup(); - - var discriminatorId = Guid.NewGuid(); - discriminatorIds.Append(discriminatorId); - - var timestampBegin = DateTimeOffset.UtcNow.AddDays(-1); - var columnNames = new List() { "A", "C" }; - var skip = 5; - var take = 5; - - var dtos = await AddRange(discriminatorId); - - //act - var response = await timestampedValuesClient.Get(discriminatorId, timestampBegin, columnNames, skip, take, CancellationToken.None); - - //assert - Assert.NotNull(response); - Assert.NotEmpty(response); - - var actualCount = response.Count(); - Assert.Equal(take, actualCount); - - var actualColumnNames = response.SelectMany(e => e.Values.Keys).Distinct().ToList(); - Assert.Equal(columnNames, actualColumnNames); - - var expectedValueKind = JsonValueKind.Number; - var actualValueKind = ((JsonElement) response.First().Values["A"]).ValueKind; - Assert.Equal(expectedValueKind, actualValueKind); - - expectedValueKind = JsonValueKind.String; - actualValueKind = ((JsonElement)response.First().Values["C"]).ValueKind; - Assert.Equal(expectedValueKind, actualValueKind); - } - - [Fact] - public async Task GetWithManyDiscriminators_returns_success() - { - //arrange - Cleanup(); - var firstDiscriminatorId = Guid.NewGuid(); discriminatorIds.Append(firstDiscriminatorId); @@ -113,7 +113,7 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest } [Fact] - public async Task GetWithManyDiscriminators_AfterSave_returns_success() + public async Task Get_AfterSave_returns_success() { //arrange Cleanup(); diff --git a/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs b/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs index 1a3ea47..3f4e0a0 100644 --- a/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs +++ b/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs @@ -3,7 +3,6 @@ using DD.Persistence.Models; using DD.Persistence.Models.Common; using DD.Persistence.Repositories; using Microsoft.EntityFrameworkCore; -using System.Linq; namespace DD.Persistence.Repository.Repositories; public class TimestampedValuesRepository : ITimestampedValuesRepository @@ -38,37 +37,7 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository return result; } - public async virtual Task>> Get(Guid discriminatorId, - DateTimeOffset? timestampBegin, - IEnumerable? columnNames, - int skip, - int take, - CancellationToken token) - { - var query = GetQueryReadOnly() - .Where(entity => entity.DiscriminatorId == discriminatorId); - - // Фильтрация по дате - if (timestampBegin.HasValue) - { - query = ApplyGeTimestamp(query, timestampBegin.Value); - } - - query = query - .OrderBy(item => item.Timestamp) - .Skip(skip) - .Take(take); - var entities = await query.ToArrayAsync(token); - - var result = entities.Select(e => Tuple.Create( - e.Timestamp, - e.Values - )); - - return result; - } - - public async virtual Task>> Get(IEnumerable discriminatorIds, + public async virtual Task>> Get(IEnumerable discriminatorIds, DateTimeOffset? timestampBegin, IEnumerable? columnNames, int skip, @@ -84,28 +53,28 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository query = ApplyGeTimestamp(query, timestampBegin.Value); } - query = query - .OrderBy(item => item.Timestamp) - .Skip(skip) - .Take(take); - var entities = await query.ToArrayAsync(token); + // Группировка отсортированных значений по DiscriminatorId + var groupQuery = query + .GroupBy(e => e.DiscriminatorId) + .Select(g => KeyValuePair.Create(g.Key, g.OrderBy(i => i.Timestamp).Skip(skip).Take(take))); + var entities = await groupQuery.ToArrayAsync(token); - var result = entities.Select(e => Tuple.Create( + var result = entities.ToDictionary(k => k.Key, v => v.Value.Select(e => ( e.Timestamp, e.Values - )); + ))); return result; } - public async virtual Task>> GetFirst(Guid discriminatorId, int takeCount, CancellationToken token) + public async virtual Task> GetFirst(Guid discriminatorId, int takeCount, CancellationToken token) { var query = GetQueryReadOnly() .OrderBy(e => e.Timestamp) .Take(takeCount); var entities = await query.ToArrayAsync(token); - var result = entities.Select(e => Tuple.Create( + var result = entities.Select(e => ( e.Timestamp, e.Values )); @@ -113,14 +82,14 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository return result; } - public async virtual Task>> GetLast(Guid discriminatorId, int takeCount, CancellationToken token) + public async virtual Task> GetLast(Guid discriminatorId, int takeCount, CancellationToken token) { var query = GetQueryReadOnly() .OrderByDescending(e => e.Timestamp) .Take(takeCount); var entities = await query.ToArrayAsync(token); - var result = entities.Select(e => Tuple.Create( + var result = entities.Select(e => ( e.Timestamp, e.Values )); @@ -129,7 +98,7 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository } // ToDo: прореживание должно осуществляться до материализации - public async virtual Task>> GetResampledData( + public async virtual Task> GetResampledData( Guid discriminatorId, DateTimeOffset dateBegin, double intervalSec = 600d, @@ -150,13 +119,13 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository return result; } - public async virtual Task>> GetGtDate(Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token) + public async virtual Task> GetGtDate(Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token) { var query = GetQueryReadOnly() .Where(e => e.Timestamp > timestampBegin); var entities = await query.ToArrayAsync(token); - var result = entities.Select(e => Tuple.Create( + var result = entities.Select(e => ( e.Timestamp, e.Values )); diff --git a/DD.Persistence/Repositories/ITimestampedValuesRepository.cs b/DD.Persistence/Repositories/ITimestampedValuesRepository.cs index c4db6ef..180bfc7 100644 --- a/DD.Persistence/Repositories/ITimestampedValuesRepository.cs +++ b/DD.Persistence/Repositories/ITimestampedValuesRepository.cs @@ -28,14 +28,14 @@ public interface ITimestampedValuesRepository : ISyncRepository, ITimeSeriesBase /// /// Получение данных с фильтрацией. Значение фильтра null - отключен /// - /// Дискриминатор (идентификатор) набора + /// Набор дискриминаторов (идентификаторов) /// Фильтр позднее даты /// Фильтр свойств набора. Можно запросить только некоторые свойства из набора /// /// /// /// - Task>> Get(Guid idDiscriminator, + Task>> Get(IEnumerable idDiscriminators, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, @@ -49,7 +49,7 @@ public interface ITimestampedValuesRepository : ISyncRepository, ITimeSeriesBase /// Количество /// /// - Task>> GetFirst(Guid discriminatorId, int takeCount, CancellationToken token); + Task> GetFirst(Guid discriminatorId, int takeCount, CancellationToken token); /// /// Получение данных с конца @@ -58,5 +58,5 @@ public interface ITimestampedValuesRepository : ISyncRepository, ITimeSeriesBase /// Количество /// /// - Task>> GetLast(Guid discriminatorId, int takeCount, CancellationToken token); + Task> GetLast(Guid discriminatorId, int takeCount, CancellationToken token); } diff --git a/DD.Persistence/RepositoriesAbstractions/ISyncRepository.cs b/DD.Persistence/RepositoriesAbstractions/ISyncRepository.cs index 95bfee2..417956d 100644 --- a/DD.Persistence/RepositoriesAbstractions/ISyncRepository.cs +++ b/DD.Persistence/RepositoriesAbstractions/ISyncRepository.cs @@ -15,7 +15,7 @@ public interface ISyncRepository // ToDo: исчерпывающая абстр /// дата начала /// /// - Task>> GetGtDate(Guid discriminatorId, DateTimeOffset dateBegin, CancellationToken token); + Task> GetGtDate(Guid discriminatorId, DateTimeOffset dateBegin, CancellationToken token); /// diff --git a/DD.Persistence/RepositoriesAbstractions/ITimeSeriesBaseRepository.cs b/DD.Persistence/RepositoriesAbstractions/ITimeSeriesBaseRepository.cs index 04b8e1a..9c7e604 100644 --- a/DD.Persistence/RepositoriesAbstractions/ITimeSeriesBaseRepository.cs +++ b/DD.Persistence/RepositoriesAbstractions/ITimeSeriesBaseRepository.cs @@ -16,7 +16,7 @@ public interface ITimeSeriesBaseRepository // ToDo: исчерпывающая /// /// /// - Task>> GetResampledData( + Task> GetResampledData( Guid discriminatorId, DateTimeOffset dateBegin, double intervalSec = 600d, diff --git a/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs b/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs index 0d075d6..27c5f16 100644 --- a/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs +++ b/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs @@ -25,19 +25,6 @@ public interface ITimestampedValuesService /// Task Count(Guid discriminatorId, CancellationToken token); - /// - /// Получение данных с фильтрацией. Значение фильтра null - отключен - /// - /// Дискриминатор (идентификатор) набора - /// Фильтр позднее даты - /// Фильтр свойств набора. Можно запросить только некоторые свойства из набора - /// - /// - /// - /// - Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, - IEnumerable? columnNames, int skip, int take, CancellationToken token); - /// /// Получение данных с фильтрацией для нескольких систем. Значение фильтра null - отключен /// diff --git a/DD.Persistence/Services/TimestampedValuesService.cs b/DD.Persistence/Services/TimestampedValuesService.cs index 31bb6b6..304fbc4 100644 --- a/DD.Persistence/Services/TimestampedValuesService.cs +++ b/DD.Persistence/Services/TimestampedValuesService.cs @@ -34,31 +34,12 @@ public class TimestampedValuesService : ITimestampedValuesService return result; } - /// - public async Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) - { - var result = await timestampedValuesRepository.Get(discriminatorId, geTimestamp, columnNames, skip, take, token); - - var dtos = await Materialize(discriminatorId, result, token); - - if (!columnNames.IsNullOrEmpty()) - { - dtos = ReduceSetColumnsByNames(dtos, columnNames!); - } - - return dtos; - } - /// public async Task> Get(IEnumerable discriminatorIds, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) { var result = await timestampedValuesRepository.Get(discriminatorIds, geTimestamp, columnNames, skip, take, token); - List dtos = []; - discriminatorIds.ForEach(async discriminatorId => { - var materializeDtos = await Materialize(discriminatorId, result, token); - dtos.AddRange(materializeDtos); - }); + var dtos = await Materialize(result, token); if (!columnNames.IsNullOrEmpty()) { @@ -73,7 +54,9 @@ public class TimestampedValuesService : ITimestampedValuesService { var result = await timestampedValuesRepository.GetFirst(discriminatorId, takeCount, token); - var dtos = await Materialize(discriminatorId, result, token); + var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) } + .ToDictionary(); + var dtos = await Materialize(resultToMaterialize, token); return dtos; } @@ -83,7 +66,9 @@ public class TimestampedValuesService : ITimestampedValuesService { var result = await timestampedValuesRepository.GetLast(discriminatorId, takeCount, token); - var dtos = await Materialize(discriminatorId, result, token); + var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) } + .ToDictionary(); + var dtos = await Materialize(resultToMaterialize, token); return dtos; } @@ -98,7 +83,9 @@ public class TimestampedValuesService : ITimestampedValuesService { var result = await timestampedValuesRepository.GetResampledData(discriminatorId, beginTimestamp, intervalSec, approxPointsCount, token); - var dtos = await Materialize(discriminatorId, result, token); + var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) } + .ToDictionary(); + var dtos = await Materialize(resultToMaterialize, token); return dtos; } @@ -107,8 +94,10 @@ public class TimestampedValuesService : ITimestampedValuesService public async Task> GetGtDate(Guid discriminatorId, DateTimeOffset beginTimestamp, CancellationToken token) { var result = await timestampedValuesRepository.GetGtDate(discriminatorId, beginTimestamp, token); - - var dtos = await Materialize(discriminatorId, result, token); + + var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) } + .ToDictionary(); + var dtos = await Materialize(resultToMaterialize, token); return dtos; } @@ -132,35 +121,38 @@ public class TimestampedValuesService : ITimestampedValuesService /// /// Преобразовать результат запроса в набор dto /// - /// /// /// /// - private async Task> Materialize(Guid dataSchemeId, IEnumerable> queryResult, CancellationToken token) + private async Task> Materialize(IDictionary> queryResult, CancellationToken token) { - var dataScheme = await dataSchemeRepository.Get(dataSchemeId, token); - if (dataScheme is null) + IEnumerable result = []; + foreach (var keyValuePair in queryResult) { - return []; + var dataScheme = await dataSchemeRepository.Get(keyValuePair.Key, token); + if (dataScheme is null) + { + continue; + } + + foreach (var tuple in keyValuePair.Value) + { + var identity = dataScheme!.PropNames; + var indexedIdentity = identity + .Select((value, index) => new { index, value }); + + var dto = new TimestampedValuesDto() + { + Timestamp = tuple.Timestamp.ToUniversalTime(), + Values = indexedIdentity + .ToDictionary(x => x.value, x => tuple.Values[x.index]) + }; + + result = result.Append(dto); + } } - var dtos = queryResult.Select(entity => - { - var dto = new TimestampedValuesDto() - { - Timestamp = entity.Item1.ToUniversalTime() - }; - - var identity = dataScheme!.PropNames; - var indexedIdentity = identity - .Select((value, index) => new { index, value }); - dto.Values = indexedIdentity - .ToDictionary(x => x.value, x => entity.Item2[x.index]); - - return dto; - }); - - return dtos; + return result; } /// From 5d820fb2c87dffb95a243f173a151195a1a167d0 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Fri, 24 Jan 2025 17:24:18 +0500 Subject: [PATCH 3/8] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20ChangeLog=20(=D1=83=D0=BF=D1=80=D0=BE=D1=89=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D1=83=D1=89=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ChangeLogController.cs | 24 +++++----- .../Clients/ChangeLogClient.cs | 31 +++++++++---- .../Clients/Interfaces/IChangeLogClient.cs | 13 +++--- .../Interfaces/Refit/IRefitChangeLogClient.cs | 46 ++++++++++++++++--- DD.Persistence.Database/Entity/ChangeLog.cs | 11 +---- .../Controllers/ChangeLogControllerTest.cs | 33 ++++--------- DD.Persistence.Models/ChangeLogDto.cs | 2 +- DD.Persistence.Models/ChangeLogValuesDto.cs | 17 +++++++ .../DataWithWellDepthAndSectionDto.cs | 32 ------------- DD.Persistence.Models/IWithSectionPart.cs | 9 ---- .../Requests/SectionPartRequest.cs | 22 --------- .../DependencyInjection.cs | 5 +- DD.Persistence.Repository/QueryBuilders.cs | 30 +----------- .../Repositories/ChangeLogRepository.cs | 21 ++++----- .../TimestampedValuesServiceShould.cs | 9 ++-- DD.Persistence/API/IChangeLogApi.cs | 18 ++++---- .../Repositories/IChangeLogRepository.cs | 11 ++--- 17 files changed, 135 insertions(+), 199 deletions(-) create mode 100644 DD.Persistence.Models/ChangeLogValuesDto.cs delete mode 100644 DD.Persistence.Models/DataWithWellDepthAndSectionDto.cs delete mode 100644 DD.Persistence.Models/IWithSectionPart.cs delete mode 100644 DD.Persistence.Models/Requests/SectionPartRequest.cs diff --git a/DD.Persistence.API/Controllers/ChangeLogController.cs b/DD.Persistence.API/Controllers/ChangeLogController.cs index 8b788c4..e4d1c09 100644 --- a/DD.Persistence.API/Controllers/ChangeLogController.cs +++ b/DD.Persistence.API/Controllers/ChangeLogController.cs @@ -24,7 +24,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)] public async Task Add( [FromRoute] Guid idDiscriminator, - [FromBody] DataWithWellDepthAndSectionDto dto, + [FromBody] ChangeLogValuesDto dto, CancellationToken token) { var userId = User.GetUserId(); @@ -37,7 +37,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)] public async Task AddRange( [FromRoute] Guid idDiscriminator, - [FromBody] IEnumerable dtos, + [FromBody] IEnumerable dtos, CancellationToken token) { var userId = User.GetUserId(); @@ -70,7 +70,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] public async Task ClearAndAddRange( [FromRoute] Guid idDiscriminator, - [FromBody] IEnumerable dtos, + [FromBody] IEnumerable dtos, CancellationToken token) { var userId = User.GetUserId(); @@ -81,7 +81,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpPut] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] public async Task Update( - DataWithWellDepthAndSectionDto dto, + ChangeLogValuesDto dto, CancellationToken token) { var userId = User.GetUserId(); @@ -93,7 +93,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi [HttpPut("range")] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] public async Task UpdateRange( - IEnumerable dtos, + IEnumerable dtos, CancellationToken token) { var userId = User.GetUserId(); @@ -103,29 +103,27 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpGet("{idDiscriminator}")] - [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] public async Task GetCurrent( [FromRoute] Guid idDiscriminator, - [FromQuery] SectionPartRequest filterRequest, [FromQuery] PaginationRequest paginationRequest, CancellationToken token) { var moment = new DateTimeOffset(3000, 1, 1, 0, 0, 0, TimeSpan.Zero); - var result = await repository.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token); + var result = await repository.GetByDate(idDiscriminator, moment, paginationRequest, token); return Ok(result); } [HttpGet("moment/{idDiscriminator}")] - [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(PaginationContainer), (int)HttpStatusCode.OK)] public async Task GetByDate( [FromRoute] Guid idDiscriminator, DateTimeOffset moment, - [FromQuery] SectionPartRequest filterRequest, [FromQuery] PaginationRequest paginationRequest, CancellationToken token) { - var result = await repository.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token); + var result = await repository.GetByDate(idDiscriminator, moment, paginationRequest, token); return Ok(result); } @@ -155,9 +153,9 @@ public class ChangeLogController : ControllerBase, IChangeLogApi } [HttpGet("part/{idDiscriminator}")] - [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.NoContent)] - public async Task>> GetPart([FromRoute] Guid idDiscriminator, DateTimeOffset dateBegin, int take = 86400, CancellationToken token = default) + public async Task>> GetPart([FromRoute] Guid idDiscriminator, DateTimeOffset dateBegin, int take = 86400, CancellationToken token = default) { var result = await repository.GetGtDate(idDiscriminator, dateBegin, token); diff --git a/DD.Persistence.Client/Clients/ChangeLogClient.cs b/DD.Persistence.Client/Clients/ChangeLogClient.cs index e4f5904..fa73ba9 100644 --- a/DD.Persistence.Client/Clients/ChangeLogClient.cs +++ b/DD.Persistence.Client/Clients/ChangeLogClient.cs @@ -7,16 +7,19 @@ using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Models.Common; namespace DD.Persistence.Client.Clients; +/// public class ChangeLogClient : BaseClient, IChangeLogClient { private readonly IRefitChangeLogClient refitChangeLogClient; + /// public ChangeLogClient(IRefitClientFactory refitClientFactory, ILogger logger) : base(logger) { this.refitChangeLogClient = refitClientFactory.Create(); } - public async Task ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token) + /// + public async Task ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { var result = await ExecuteGetResponse( async () => await refitChangeLogClient.ClearAndAddRange(idDiscriminator, dtos, token), token); @@ -24,15 +27,17 @@ public class ChangeLogClient : BaseClient, IChangeLogClient return result; } - public async Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, - SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token) + /// + public async Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, + PaginationRequest paginationRequest, CancellationToken token) { var result = await ExecuteGetResponse( - async () => await refitChangeLogClient.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token), token); + async () => await refitChangeLogClient.GetByDate(idDiscriminator, moment, paginationRequest, token), token); - return result; + return result!; } + /// public async Task> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token) { var result = await ExecuteGetResponse( @@ -41,7 +46,8 @@ public class ChangeLogClient : BaseClient, IChangeLogClient return result!; } - public async Task Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token) + /// + public async Task Add(Guid idDiscriminator, ChangeLogValuesDto dto, CancellationToken token) { var result = await ExecutePostResponse( async () => await refitChangeLogClient.Add(idDiscriminator, dto, token), token); @@ -49,7 +55,8 @@ public class ChangeLogClient : BaseClient, IChangeLogClient return result; } - public async Task AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token) + /// + public async Task AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { var result = await ExecutePostResponse( async () => await refitChangeLogClient.AddRange(idDiscriminator, dtos, token), token); @@ -57,7 +64,8 @@ public class ChangeLogClient : BaseClient, IChangeLogClient return result; } - public async Task Update(DataWithWellDepthAndSectionDto dto, CancellationToken token) + /// + public async Task Update(ChangeLogValuesDto dto, CancellationToken token) { var result = await ExecutePostResponse( async () => await refitChangeLogClient.Update(dto, token), token); @@ -65,7 +73,8 @@ public class ChangeLogClient : BaseClient, IChangeLogClient return result; } - public async Task UpdateRange(IEnumerable dtos, CancellationToken token) + /// + public async Task UpdateRange(IEnumerable dtos, CancellationToken token) { var result = await ExecutePostResponse( async () => await refitChangeLogClient.UpdateRange(dtos, token), token); @@ -73,6 +82,7 @@ public class ChangeLogClient : BaseClient, IChangeLogClient return result; } + /// public async Task Delete(Guid id, CancellationToken token) { var result = await ExecutePostResponse( @@ -81,6 +91,7 @@ public class ChangeLogClient : BaseClient, IChangeLogClient return result; } + /// public async Task DeleteRange(IEnumerable ids, CancellationToken token) { var result = await ExecutePostResponse( @@ -89,6 +100,7 @@ public class ChangeLogClient : BaseClient, IChangeLogClient return result; } + /// public async Task GetDatesRange(Guid idDiscriminator, CancellationToken token) { var result = await ExecuteGetResponse( @@ -97,6 +109,7 @@ public class ChangeLogClient : BaseClient, IChangeLogClient return result; } + /// public void Dispose() { refitChangeLogClient.Dispose(); diff --git a/DD.Persistence.Client/Clients/Interfaces/IChangeLogClient.cs b/DD.Persistence.Client/Clients/Interfaces/IChangeLogClient.cs index f81ac8d..16a491c 100644 --- a/DD.Persistence.Client/Clients/Interfaces/IChangeLogClient.cs +++ b/DD.Persistence.Client/Clients/Interfaces/IChangeLogClient.cs @@ -16,7 +16,7 @@ public interface IChangeLogClient : IDisposable /// /// /// - Task Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); + Task Add(Guid idDiscriminator, ChangeLogValuesDto dto, CancellationToken token); /// /// Добавить несколько записей @@ -25,7 +25,7 @@ public interface IChangeLogClient : IDisposable /// /// /// - Task AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Импорт с заменой: удаление старых строк и добавление новых @@ -34,7 +34,7 @@ public interface IChangeLogClient : IDisposable /// /// /// - Task ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Удалить одну запись @@ -57,11 +57,10 @@ public interface IChangeLogClient : IDisposable /// /// /// - /// /// /// /// - Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token); + Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, PaginationRequest paginationRequest, CancellationToken token); /// /// Получение исторических данных за определенный период времени @@ -87,7 +86,7 @@ public interface IChangeLogClient : IDisposable /// /// /// - Task Update(DataWithWellDepthAndSectionDto dto, CancellationToken token); + Task Update(ChangeLogValuesDto dto, CancellationToken token); /// /// Обновить несколько записей @@ -95,5 +94,5 @@ public interface IChangeLogClient : IDisposable /// /// /// - Task UpdateRange(IEnumerable dtos, CancellationToken token); + Task UpdateRange(IEnumerable dtos, CancellationToken token); } \ No newline at end of file diff --git a/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitChangeLogClient.cs b/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitChangeLogClient.cs index 8e35b4e..a07fac3 100644 --- a/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitChangeLogClient.cs +++ b/DD.Persistence.Client/Clients/Interfaces/Refit/IRefitChangeLogClient.cs @@ -5,42 +5,74 @@ using Refit; namespace DD.Persistence.Client.Clients.Interfaces.Refit; +/// +/// Refit интерфейс для IRefitChangeLogClient +/// public interface IRefitChangeLogClient : IRefitClient, IDisposable { private const string BaseRoute = "/api/ChangeLog"; + /// + /// Импорт с заменой: удаление старых строк и добавление новых + /// [Post($"{BaseRoute}/replace/{{idDiscriminator}}")] - Task> ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task> ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + /// + /// Получение актуальных данных на определенную дату (с пагинацией) + /// [Get($"{BaseRoute}/moment/{{idDiscriminator}}")] - Task>> GetByDate( + Task>> GetByDate( Guid idDiscriminator, DateTimeOffset moment, - [Query] SectionPartRequest filterRequest, [Query] PaginationRequest paginationRequest, CancellationToken token); + /// + /// Получение исторических данных за определенный период времени + /// [Get($"{BaseRoute}/history/{{idDiscriminator}}")] Task>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token); + /// + /// Добавить одну запись + /// [Post($"{BaseRoute}/{{idDiscriminator}}")] - Task> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); + Task> Add(Guid idDiscriminator, ChangeLogValuesDto dto, CancellationToken token); + /// + /// Добавить несколько записей + /// [Post($"{BaseRoute}/range/{{idDiscriminator}}")] - Task> AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task> AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + /// + /// Обновить одну запись + /// [Put($"{BaseRoute}")] - Task> Update(DataWithWellDepthAndSectionDto dto, CancellationToken token); + Task> Update(ChangeLogValuesDto dto, CancellationToken token); + /// + /// Обновить несколько записей + /// [Put($"{BaseRoute}/range")] - Task> UpdateRange(IEnumerable dtos, CancellationToken token); + Task> UpdateRange(IEnumerable dtos, CancellationToken token); + /// + /// Удалить одну запись + /// [Delete($"{BaseRoute}")] Task> Delete(Guid id, CancellationToken token); + /// + /// Удалить несколько записей + /// [Delete($"{BaseRoute}/range")] Task> DeleteRange([Body] IEnumerable ids, CancellationToken token); + /// + /// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени) + /// [Get($"{BaseRoute}/datesRange/{{idDiscriminator}}")] Task> GetDatesRange(Guid idDiscriminator, CancellationToken token); diff --git a/DD.Persistence.Database/Entity/ChangeLog.cs b/DD.Persistence.Database/Entity/ChangeLog.cs index d874ea2..7b489ea 100644 --- a/DD.Persistence.Database/Entity/ChangeLog.cs +++ b/DD.Persistence.Database/Entity/ChangeLog.cs @@ -10,7 +10,7 @@ namespace DD.Persistence.Database.Model; /// /// Часть записи, описывающая изменение /// -public class ChangeLog : IChangeLog, IWithSectionPart +public class ChangeLog : IChangeLog { [Key, Comment("Ключ записи")] public Guid Id { get; set; } @@ -33,15 +33,6 @@ public class ChangeLog : IChangeLog, IWithSectionPart [Comment("Id заменяющей записи")] public Guid? IdNext { get; set; } - [Comment("Глубина забоя на дату начала интервала")] - public double DepthStart { get; set; } - - [Comment("Глубина забоя на дату окончания интервала")] - public double DepthEnd { get; set; } - - [Comment("Ключ секции")] - public Guid IdSection { get; set; } - [Column(TypeName = "jsonb"), Comment("Значение")] public required IDictionary Value { get; set; } } diff --git a/DD.Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs b/DD.Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs index 64419e7..947a196 100644 --- a/DD.Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs +++ b/DD.Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs @@ -52,7 +52,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest var insertedCount = 10; var createdResult = CreateChangeLogItems(insertedCount, (-15, 15)); var idDiscriminator = createdResult.Item1; - var dtos = createdResult.Item2.Select(e => e.Adapt()); + var dtos = createdResult.Item2.Select(e => e.Adapt()); // act var result = await client.ClearAndAddRange(idDiscriminator, dtos, new CancellationToken()); @@ -106,8 +106,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest var entity = dbContext.ChangeLog .Where(x => x.IdDiscriminator == idDiscriminator) .FirstOrDefault(); - dto = entity.Adapt(); - dto.DepthEnd += 10; + dto = entity.Adapt(); // act result = await client.Update(dto, new CancellationToken()); @@ -149,12 +148,9 @@ public class ChangeLogControllerTest : BaseIntegrationTest dbContext.ChangeLog.AddRange(entities); dbContext.SaveChanges(); - dtos = entities.Select(c => new DataWithWellDepthAndSectionDto() + dtos = entities.Select(c => new ChangeLogValuesDto() { - DepthEnd = c.DepthEnd + 10, - DepthStart = c.DepthStart + 10, Id = c.Id, - IdSection = c.IdSection, Value = c.Value }).ToArray(); @@ -245,12 +241,6 @@ public class ChangeLogControllerTest : BaseIntegrationTest var deletedCount = await client.DeleteRange(idsToDelete, new CancellationToken()); - var filterRequest = new SectionPartRequest() - { - DepthStart = 0, - DepthEnd = 1000, - }; - var paginationRequest = new PaginationRequest() { Skip = 0, @@ -259,7 +249,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest }; var moment = DateTimeOffset.UtcNow.AddDays(16); - var result = await client.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, new CancellationToken()); + var result = await client.GetByDate(idDiscriminator, moment, paginationRequest, new CancellationToken()); Assert.NotNull(result); @@ -292,11 +282,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest var idDiscriminator = changeLogItems.Item1; var entities = changeLogItems.Item2; - foreach (var entity in entities) - { - entity.DepthEnd += 10; - } - var dtos = entities.Select(e => e.Adapt()).ToArray(); + var dtos = entities.Select(e => e.Adapt()).ToArray(); await client.UpdateRange(dtos, new CancellationToken()); //act @@ -310,19 +296,16 @@ public class ChangeLogControllerTest : BaseIntegrationTest } - private static IEnumerable Generate(int count) + private static IEnumerable Generate(int count) { for (int i = 0; i < count; i++) - yield return new DataWithWellDepthAndSectionDto() + yield return new ChangeLogValuesDto() { Value = new Dictionary() { { "Key", 1 } }, - DepthStart = generatorRandomDigits.Next(1, 5), - DepthEnd = generatorRandomDigits.Next(5, 15), - Id = Guid.NewGuid(), - IdSection = Guid.NewGuid() + Id = Guid.NewGuid() }; } diff --git a/DD.Persistence.Models/ChangeLogDto.cs b/DD.Persistence.Models/ChangeLogDto.cs index 8f2725b..d277bd8 100644 --- a/DD.Persistence.Models/ChangeLogDto.cs +++ b/DD.Persistence.Models/ChangeLogDto.cs @@ -38,5 +38,5 @@ public class ChangeLogDto /// /// Объект записи /// - public DataWithWellDepthAndSectionDto Value { get; set; } = default!; + public ChangeLogValuesDto Value { get; set; } = default!; } diff --git a/DD.Persistence.Models/ChangeLogValuesDto.cs b/DD.Persistence.Models/ChangeLogValuesDto.cs new file mode 100644 index 0000000..548a7ba --- /dev/null +++ b/DD.Persistence.Models/ChangeLogValuesDto.cs @@ -0,0 +1,17 @@ +namespace DD.Persistence.Models; + +/// +/// Dto для хранения записей, содержащих начальную и конечную глубину забоя, а также секцию +/// +public class ChangeLogValuesDto +{ + /// + /// Ключ записи + /// + public Guid Id { get; set; } + + /// + /// Объект записи + /// + public required IDictionary Value { get; set; } +} diff --git a/DD.Persistence.Models/DataWithWellDepthAndSectionDto.cs b/DD.Persistence.Models/DataWithWellDepthAndSectionDto.cs deleted file mode 100644 index 7644229..0000000 --- a/DD.Persistence.Models/DataWithWellDepthAndSectionDto.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace DD.Persistence.Models; - -/// -/// Dto для хранения записей, содержащих начальную и конечную глубину забоя, а также секцию -/// -public class DataWithWellDepthAndSectionDto -{ - /// - /// Ключ записи - /// - public Guid Id { get; set; } - - /// - /// Глубина забоя на дату начала интервала - /// - public double DepthStart { get; set; } - - /// - /// Глубина забоя на дату окончания интервала - /// - public double DepthEnd { get; set; } - - /// - /// Ключ секции - /// - public Guid IdSection { get; set; } - - /// - /// Объект записи - /// - public required IDictionary Value { get; set; } -} diff --git a/DD.Persistence.Models/IWithSectionPart.cs b/DD.Persistence.Models/IWithSectionPart.cs deleted file mode 100644 index 0d3ff1f..0000000 --- a/DD.Persistence.Models/IWithSectionPart.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace DD.Persistence.ModelsAbstractions; -public interface IWithSectionPart -{ - public double DepthStart { get; set; } - - public double DepthEnd { get; set; } - - public Guid IdSection { get; set; } -} diff --git a/DD.Persistence.Models/Requests/SectionPartRequest.cs b/DD.Persistence.Models/Requests/SectionPartRequest.cs deleted file mode 100644 index 73319c6..0000000 --- a/DD.Persistence.Models/Requests/SectionPartRequest.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace DD.Persistence.Models.Requests; - -/// -/// Запрос для фильтрации данных по секции и глубине -/// -public class SectionPartRequest -{ - /// - /// Глубина забоя на дату начала интервала - /// - public double? DepthStart { get; set; } - - /// - /// Глубина забоя на дату окончания интервала - /// - public double? DepthEnd { get; set; } - - /// - /// Ключ секции - /// - public Guid? IdSection { get; set; } -} diff --git a/DD.Persistence.Repository/DependencyInjection.cs b/DD.Persistence.Repository/DependencyInjection.cs index d0a5d37..1424d37 100644 --- a/DD.Persistence.Repository/DependencyInjection.cs +++ b/DD.Persistence.Repository/DependencyInjection.cs @@ -18,11 +18,8 @@ public static class DependencyInjection .Ignore(dest => dest.System, dest => dest.SystemId); TypeAdapterConfig.NewConfig() - .Map(dest => dest.Value, src => new DataWithWellDepthAndSectionDto() + .Map(dest => dest.Value, src => new ChangeLogValuesDto() { - DepthEnd = src.DepthEnd, - DepthStart = src.DepthStart, - IdSection = src.IdSection, Value = src.Value, Id = src.Id }); diff --git a/DD.Persistence.Repository/QueryBuilders.cs b/DD.Persistence.Repository/QueryBuilders.cs index 53e72a4..52b6429 100644 --- a/DD.Persistence.Repository/QueryBuilders.cs +++ b/DD.Persistence.Repository/QueryBuilders.cs @@ -12,25 +12,6 @@ namespace DD.Persistence.Repository; /// public static class QueryBuilders { - public static IQueryable Apply(this IQueryable query, SectionPartRequest request) - where TEntity : class, IWithSectionPart - { - if (request.IdSection.HasValue) - { - query = query.Where(e => e.IdSection == request.IdSection); - } - if (request.DepthStart.HasValue) - { - query = query.Where(e => e.DepthStart >= request.DepthStart); - } - if (request.DepthEnd.HasValue) - { - query = query.Where(e => e.DepthEnd <= request.DepthEnd); - } - - return query; - } - public static IQueryable Apply(this IQueryable query, DateTimeOffset momentUtc) where TEntity : class, IChangeLog { @@ -49,17 +30,10 @@ public static class QueryBuilders PaginationRequest request, Func Convert, CancellationToken token) - where TEntity : class, IWithSectionPart + where TEntity : class where TDto : class { - if (String.IsNullOrEmpty(request.SortSettings)) - { - query = query - .OrderBy(e => e.IdSection) - .ThenBy(e => e.DepthStart) - .ThenBy(e => e.DepthEnd); - } - else + if (!String.IsNullOrEmpty(request.SortSettings)) { query = query.SortBy(request.SortSettings); } diff --git a/DD.Persistence.Repository/Repositories/ChangeLogRepository.cs b/DD.Persistence.Repository/Repositories/ChangeLogRepository.cs index 60fe08e..ebb3859 100644 --- a/DD.Persistence.Repository/Repositories/ChangeLogRepository.cs +++ b/DD.Persistence.Repository/Repositories/ChangeLogRepository.cs @@ -17,7 +17,7 @@ public class ChangeLogRepository : IChangeLogRepository this.db = db; } - public async Task AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) + public async Task AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { var entities = new List(); foreach (var dto in dtos) @@ -76,7 +76,7 @@ public class ChangeLogRepository : IChangeLogRepository return await db.SaveChangesAsync(token); } - public async Task ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) + public async Task ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token) { var result = 0; @@ -91,7 +91,7 @@ public class ChangeLogRepository : IChangeLogRepository return result; } - public async Task UpdateRange(Guid idEditor, IEnumerable dtos, CancellationToken token) + public async Task UpdateRange(Guid idEditor, IEnumerable dtos, CancellationToken token) { var dbSet = db.Set(); @@ -127,16 +127,14 @@ public class ChangeLogRepository : IChangeLogRepository } - public async Task> GetByDate( + public async Task> GetByDate( Guid idDiscriminator, DateTimeOffset momentUtc, - SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token) { var query = CreateQuery(idDiscriminator); query = query.Apply(momentUtc); - query = query.Apply(filterRequest); var result = await query.ApplyPagination(paginationRequest, Convert, token); @@ -196,7 +194,7 @@ public class ChangeLogRepository : IChangeLogRepository return datesOnly; } - private static ChangeLog CreateEntityFromDto(Guid idAuthor, Guid idDiscriminator, DataWithWellDepthAndSectionDto dto) + private static ChangeLog CreateEntityFromDto(Guid idAuthor, Guid idDiscriminator, ChangeLogValuesDto dto) { var entity = new ChangeLog() { @@ -206,16 +204,13 @@ public class ChangeLogRepository : IChangeLogRepository IdDiscriminator = idDiscriminator, IdEditor = idAuthor, - Value = dto.Value, - IdSection = dto.IdSection, - DepthStart = dto.DepthStart, - DepthEnd = dto.DepthEnd, + Value = dto.Value }; return entity; } - public async Task> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token) + public async Task> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token) { var date = dateBegin.ToUniversalTime(); var query = this.db.Set() @@ -256,5 +251,5 @@ public class ChangeLogRepository : IChangeLogRepository }; } - private DataWithWellDepthAndSectionDto Convert(ChangeLog entity) => entity.Adapt(); + private ChangeLogValuesDto Convert(ChangeLog entity) => entity.Adapt(); } diff --git a/DD.Persistence.Test/TimestampedValuesServiceShould.cs b/DD.Persistence.Test/TimestampedValuesServiceShould.cs index 5f3e65b..0acb6de 100644 --- a/DD.Persistence.Test/TimestampedValuesServiceShould.cs +++ b/DD.Persistence.Test/TimestampedValuesServiceShould.cs @@ -18,11 +18,14 @@ public class TimestampedValuesServiceShould [Fact] public async Task TestServiceEfficiency() { - var discriminatorId = Guid.NewGuid(); + var discriminatorIds = new[] { Guid.NewGuid(), Guid.NewGuid() }; const int count = 10; var dtos = Generate(count, DateTimeOffset.UtcNow); var addRangeResult = await timestampedValuesService - .AddRange(discriminatorId, dtos, CancellationToken.None); + .AddRange(discriminatorIds.First(), dtos, CancellationToken.None); + Assert.Equal(0, addRangeResult); + addRangeResult = await timestampedValuesService + .AddRange(discriminatorIds.Last(), dtos, CancellationToken.None); Assert.Equal(0, addRangeResult); var columnNames = new[] { "A", "B", "C", "D" }; @@ -30,7 +33,7 @@ public class TimestampedValuesServiceShould .AddHours(-1) .ToUniversalTime(); var getResult = await timestampedValuesService - .Get(discriminatorId, geTimestamp, columnNames, 0, count, CancellationToken.None); + .Get(discriminatorIds, geTimestamp, columnNames, 0, count, CancellationToken.None); Assert.NotNull(getResult); Assert.Empty(getResult); } diff --git a/DD.Persistence/API/IChangeLogApi.cs b/DD.Persistence/API/IChangeLogApi.cs index e865894..5389ba2 100644 --- a/DD.Persistence/API/IChangeLogApi.cs +++ b/DD.Persistence/API/IChangeLogApi.cs @@ -7,7 +7,7 @@ namespace DD.Persistence.API; /// /// Интерфейс для работы с API журнала изменений /// -public interface IChangeLogApi : ISyncWithDiscriminatorApi +public interface IChangeLogApi : ISyncWithDiscriminatorApi { /// /// Импорт с заменой: удаление старых строк и добавление новых @@ -16,28 +16,26 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi /// /// - Task ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task ClearAndAddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Получение данных на текущую дату (с пагинацией) /// /// - /// параметры запроса фильтрации /// параметры запроса пагинации /// /// - Task GetCurrent(Guid idDiscriminator, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token); + Task GetCurrent(Guid idDiscriminator, PaginationRequest paginationRequest, CancellationToken token); /// /// Получение данных на определенную дату (с пагинацией) /// /// /// - /// параметры запроса фильтрации /// параметры запроса пагинации /// /// - Task GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token); + Task GetByDate(Guid idDiscriminator, DateTimeOffset moment, PaginationRequest paginationRequest, CancellationToken token); /// /// Получение исторических данных за определенный период времени @@ -56,7 +54,7 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi /// /// - Task Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); + Task Add(Guid idDiscriminator, ChangeLogValuesDto dto, CancellationToken token); /// /// Добавить несколько записей @@ -65,7 +63,7 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi /// /// - Task AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task AddRange(Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Обновить одну запись @@ -73,7 +71,7 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi /// /// - Task Update(DataWithWellDepthAndSectionDto dto, CancellationToken token); + Task Update(ChangeLogValuesDto dto, CancellationToken token); /// /// Обновить несколько записей @@ -81,7 +79,7 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi /// /// - Task UpdateRange(IEnumerable dtos, CancellationToken token); + Task UpdateRange(IEnumerable dtos, CancellationToken token); /// /// Удалить одну запись diff --git a/DD.Persistence/Repositories/IChangeLogRepository.cs b/DD.Persistence/Repositories/IChangeLogRepository.cs index 6c39e24..3305e65 100644 --- a/DD.Persistence/Repositories/IChangeLogRepository.cs +++ b/DD.Persistence/Repositories/IChangeLogRepository.cs @@ -8,7 +8,7 @@ namespace DD.Persistence.Repositories; /// Интерфейс для работы с историческими данными /// /// -public interface IChangeLogRepository : ISyncWithDiscriminatorRepository +public interface IChangeLogRepository : ISyncWithDiscriminatorRepository { /// /// Добавление записей @@ -18,7 +18,7 @@ public interface IChangeLogRepository : ISyncWithDiscriminatorRepository /// /// - Task AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Пометить записи как удаленные @@ -46,7 +46,7 @@ public interface IChangeLogRepository : ISyncWithDiscriminatorRepository /// /// - Task ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); + Task ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable dtos, CancellationToken token); /// /// Редактирование записей @@ -55,18 +55,17 @@ public interface IChangeLogRepository : ISyncWithDiscriminatorRepository /// /// - Task UpdateRange(Guid idEditor, IEnumerable dtos, CancellationToken token); + Task UpdateRange(Guid idEditor, IEnumerable dtos, CancellationToken token); /// /// Получение актуальных записей на определенный момент времени (с пагинацией) /// /// /// текущий момент времени - /// параметры запроса фильтрации /// параметры запроса пагинации /// /// - Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token); + Task> GetByDate(Guid idDiscriminator, DateTimeOffset moment, PaginationRequest paginationRequest, CancellationToken token); /// /// Получение измененных записей за период времени From a649fac48ecf424d752025d757f3611cf6e8b69e Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Mon, 27 Jan 2025 09:06:07 +0500 Subject: [PATCH 4/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BF=D1=83=D0=B1=D0=BB=D0=B8=D0=BA=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8E=20=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82=D0=B0=20=D0=B2=20?= =?UTF-8?q?.yaml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/integrationTests.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/integrationTests.yaml b/.gitea/workflows/integrationTests.yaml index f5069b9..6ffe4eb 100644 --- a/.gitea/workflows/integrationTests.yaml +++ b/.gitea/workflows/integrationTests.yaml @@ -1,6 +1,9 @@ name: Unit tests run-name: ${{ gitea.actor }} is testing -on: push +on: + push: + branches: + - master jobs: test: @@ -32,7 +35,13 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: 9.0.x + - name: Add gitea as nuget source + run: dotnet nuget add source --name gitea --username publisher --password ${{ secrets.PUBLISHER_PASSWORD }} --store-password-in-clear-text https://git.ddrilling.ru/api/packages/DDrilling/nuget/index.json - name: Check out repository code uses: actions/checkout@v4 - name: Run integration tests run: dotnet test DD.Persistence.IntegrationTests + - name: Pack Persistence Client + run: dotnet pack DD.Persistence.Client/DD.Persistence.Client.csproj -c Debug -o ./artifacts + - name: Publish Persistence Client Package + run: dotnet nuget push ./artifacts/DD.Persistence.Client.*.nupkg --source gitea --skip-duplicate From b6f4aed8e467591e328d131484e01d559f64089d Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Mon, 27 Jan 2025 09:06:57 +0500 Subject: [PATCH 5/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20.yaml=20=D0=B2=20=D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DD.Persistence.sln | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/DD.Persistence.sln b/DD.Persistence.sln index 03f0be9..926e688 100644 --- a/DD.Persistence.sln +++ b/DD.Persistence.sln @@ -30,6 +30,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DD.Persistence.Test", "DD.Persistence.Test\DD.Persistence.Test.csproj", "{B8C774E6-6B75-41AC-B3CF-10BD3623B2FA}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Элементы решения", "Элементы решения", "{E0CEF8FC-C131-4CF3-9F0A-E7B4F895B811}" + ProjectSection(SolutionItems) = preProject + .gitea\workflows\integrationTests.yaml = .gitea\workflows\integrationTests.yaml + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU From 986d492862b76386586e3392531e1dcb2edac5ee Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Mon, 27 Jan 2025 09:17:40 +0500 Subject: [PATCH 6/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C=D0=BD=D0=BE=D0=B5?= =?UTF-8?q?=20=D1=82=D0=B5=D1=81=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B2=20.yaml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/integrationTests.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitea/workflows/integrationTests.yaml b/.gitea/workflows/integrationTests.yaml index 6ffe4eb..48b1a69 100644 --- a/.gitea/workflows/integrationTests.yaml +++ b/.gitea/workflows/integrationTests.yaml @@ -41,6 +41,8 @@ jobs: uses: actions/checkout@v4 - name: Run integration tests run: dotnet test DD.Persistence.IntegrationTests + - name: Run unit tests + run: dotnet test DD.Persistence.Test --no-build - name: Pack Persistence Client run: dotnet pack DD.Persistence.Client/DD.Persistence.Client.csproj -c Debug -o ./artifacts - name: Publish Persistence Client Package From f250db8b7fde115091cdee74b9f49c704a0c9be2 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Mon, 27 Jan 2025 10:24:51 +0500 Subject: [PATCH 7/8] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D1=82=D1=8C=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B=D0=B9=20=D1=83=D1=87?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=BE=D0=BA=20=D0=BA=D0=BE=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimestampedValuesControllerTest.cs | 55 ------------------- 1 file changed, 55 deletions(-) diff --git a/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs b/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs index 3131ec5..c6642a5 100644 --- a/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs +++ b/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs @@ -38,61 +38,6 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest await AddRange(discriminatorId); } - //[Fact] - //public async Task Get_returns_success() - //{ - // //arrange - // Cleanup(); - - // var discriminatorId = Guid.NewGuid(); - // discriminatorIds.Append(discriminatorId); - - // //act - // var response = await timestampedValuesClient.Get(discriminatorId, null, null, 0, 1, CancellationToken.None); - - // //assert - // Assert.Null(response); - //} - - //[Fact] - - //public async Task Get_AfterSave_returns_success() - //{ - // //arrange - // Cleanup(); - - // var discriminatorId = Guid.NewGuid(); - // discriminatorIds.Append(discriminatorId); - - // var timestampBegin = DateTimeOffset.UtcNow.AddDays(-1); - // var columnNames = new List() { "A", "C" }; - // var skip = 5; - // var take = 5; - - // var dtos = await AddRange(discriminatorId); - - // //act - // var response = await timestampedValuesClient.Get(discriminatorId, timestampBegin, columnNames, skip, take, CancellationToken.None); - - // //assert - // Assert.NotNull(response); - // Assert.NotEmpty(response); - - // var actualCount = response.Count(); - // Assert.Equal(take, actualCount); - - // var actualColumnNames = response.SelectMany(e => e.Values.Keys).Distinct().ToList(); - // Assert.Equal(columnNames, actualColumnNames); - - // var expectedValueKind = JsonValueKind.Number; - // var actualValueKind = ((JsonElement) response.First().Values["A"]).ValueKind; - // Assert.Equal(expectedValueKind, actualValueKind); - - // expectedValueKind = JsonValueKind.String; - // actualValueKind = ((JsonElement)response.First().Values["C"]).ValueKind; - // Assert.Equal(expectedValueKind, actualValueKind); - //} - [Fact] public async Task Get_returns_success() { From 911508632e96b2e060b67a0556e356704e6ebdd8 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Mon, 27 Jan 2025 11:16:24 +0500 Subject: [PATCH 8/8] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/TimestampedValuesController.cs | 13 ++++++++----- .../Repositories/TimestampedValuesRepository.cs | 15 +++++---------- .../Interfaces/ITimestampedValuesService.cs | 16 ---------------- .../Services/TimestampedValuesService.cs | 16 ---------------- 4 files changed, 13 insertions(+), 47 deletions(-) diff --git a/DD.Persistence.API/Controllers/TimestampedValuesController.cs b/DD.Persistence.API/Controllers/TimestampedValuesController.cs index bb4934c..fe97476 100644 --- a/DD.Persistence.API/Controllers/TimestampedValuesController.cs +++ b/DD.Persistence.API/Controllers/TimestampedValuesController.cs @@ -1,6 +1,8 @@ using DD.Persistence.Models; using DD.Persistence.Models.Common; +using DD.Persistence.Repositories; using DD.Persistence.Services.Interfaces; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Net; @@ -10,15 +12,16 @@ namespace DD.Persistence.API.Controllers; /// Хранение наборов данных с отметкой времени. /// [ApiController] -//[Authorize] +[Authorize] [Route("api/[controller]")] public class TimestampedValuesController : ControllerBase { private readonly ITimestampedValuesService timestampedValuesService; - - public TimestampedValuesController(ITimestampedValuesService repository) + private readonly ITimestampedValuesRepository timestampedValuesRepository; + public TimestampedValuesController(ITimestampedValuesService repository, ITimestampedValuesRepository timestampedValuesRepository) { this.timestampedValuesService = repository; + this.timestampedValuesRepository = timestampedValuesRepository; } /// @@ -130,7 +133,7 @@ public class TimestampedValuesController : ControllerBase [HttpGet("{discriminatorId}/count")] public async Task> Count([FromRoute] Guid discriminatorId, CancellationToken token) { - var result = await timestampedValuesService.Count(discriminatorId, token); + var result = await timestampedValuesRepository.Count(discriminatorId, token); return Ok(result); } @@ -143,7 +146,7 @@ public class TimestampedValuesController : ControllerBase [HttpGet("{discriminatorId}/datesRange")] public async Task> GetDatesRange([FromRoute] Guid discriminatorId, CancellationToken token) { - var result = await timestampedValuesService.GetDatesRange(discriminatorId, token); + var result = await timestampedValuesRepository.GetDatesRange(discriminatorId, token); return Ok(result); } diff --git a/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs b/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs index 3f4e0a0..2005a5a 100644 --- a/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs +++ b/DD.Persistence.Repository/Repositories/TimestampedValuesRepository.cs @@ -18,17 +18,12 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository public async virtual Task AddRange(Guid discriminatorId, IEnumerable dtos, CancellationToken token) { - var timestampedValuesEntities = new List(); - foreach (var dto in dtos) + var timestampedValuesEntities = dtos.Select(dto => new TimestampedValues() { - var timestampedValuesEntity = new TimestampedValues() - { - DiscriminatorId = discriminatorId, - Timestamp = dto.Timestamp.ToUniversalTime(), - Values = dto.Values.Values.ToArray() - }; - timestampedValuesEntities.Add(timestampedValuesEntity); - } + DiscriminatorId = discriminatorId, + Timestamp = dto.Timestamp.ToUniversalTime(), + Values = dto.Values.Values.ToArray() + }); await db.Set().AddRangeAsync(timestampedValuesEntities, token); diff --git a/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs b/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs index 27c5f16..317eb8c 100644 --- a/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs +++ b/DD.Persistence/Services/Interfaces/ITimestampedValuesService.cs @@ -17,14 +17,6 @@ public interface ITimestampedValuesService /// Task AddRange(Guid discriminatorId, IEnumerable dtos, CancellationToken token); - /// - /// Количество записей по указанному набору в БД. Для пагинации - /// - /// Дискриминатор (идентификатор) набора - /// - /// - Task Count(Guid discriminatorId, CancellationToken token); - /// /// Получение данных с фильтрацией для нескольких систем. Значение фильтра null - отключен /// @@ -75,12 +67,4 @@ public interface ITimestampedValuesService /// /// Task> GetResampledData(Guid discriminatorId, DateTimeOffset timestampBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default); - - /// - /// Получить диапазон дат, для которых есть данные - /// - /// - /// - /// - Task GetDatesRange(Guid discriminatorId, CancellationToken token); } \ No newline at end of file diff --git a/DD.Persistence/Services/TimestampedValuesService.cs b/DD.Persistence/Services/TimestampedValuesService.cs index 304fbc4..cbcb73c 100644 --- a/DD.Persistence/Services/TimestampedValuesService.cs +++ b/DD.Persistence/Services/TimestampedValuesService.cs @@ -102,22 +102,6 @@ public class TimestampedValuesService : ITimestampedValuesService return dtos; } - /// - public async Task Count(Guid discriminatorId, CancellationToken token) - { - var result = await timestampedValuesRepository.Count(discriminatorId, token); - - return result; - } - - /// - public async virtual Task GetDatesRange(Guid discriminatorId, CancellationToken token) - { - var result = await timestampedValuesRepository.GetDatesRange(discriminatorId, token); - - return result; - } - /// /// Преобразовать результат запроса в набор dto ///