Compare commits
No commits in common. "master" and "dev" have entirely different histories.
@ -1,9 +1,6 @@
|
|||||||
name: Unit tests
|
name: Unit tests
|
||||||
run-name: ${{ gitea.actor }} is testing
|
run-name: ${{ gitea.actor }} is testing
|
||||||
on:
|
on: push
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@ -35,19 +32,7 @@ jobs:
|
|||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: 9.0.x
|
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
|
- name: Check out repository code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Run integration tests
|
- name: Run integration tests
|
||||||
run: dotnet test DD.Persistence.IntegrationTests
|
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: Pack Persistence Models
|
|
||||||
run: dotnet pack DD.Persistence.Models/DD.Persistence.Models.csproj -c Debug -o ./artifacts
|
|
||||||
- name: Publish Persistence Client Package
|
|
||||||
run: dotnet nuget push ./artifacts/DD.Persistence.Client.*.nupkg --source gitea --skip-duplicate
|
|
||||||
- name: Publish Persistence Models Package
|
|
||||||
run: dotnet nuget push ./artifacts/DD.Persistence.Models.*.nupkg --source gitea --skip-duplicate
|
|
||||||
|
@ -4,7 +4,6 @@ using DD.Persistence.Models;
|
|||||||
using DD.Persistence.Models.Requests;
|
using DD.Persistence.Models.Requests;
|
||||||
using DD.Persistence.Repositories;
|
using DD.Persistence.Repositories;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.API.Controllers;
|
namespace DD.Persistence.API.Controllers;
|
||||||
|
|
||||||
@ -24,7 +23,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
|
|||||||
[ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)]
|
[ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)]
|
||||||
public async Task<IActionResult> Add(
|
public async Task<IActionResult> Add(
|
||||||
[FromRoute] Guid idDiscriminator,
|
[FromRoute] Guid idDiscriminator,
|
||||||
[FromBody] ChangeLogValuesDto dto,
|
[FromBody] DataWithWellDepthAndSectionDto dto,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var userId = User.GetUserId<Guid>();
|
var userId = User.GetUserId<Guid>();
|
||||||
@ -37,7 +36,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
|
|||||||
[ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)]
|
[ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)]
|
||||||
public async Task<IActionResult> AddRange(
|
public async Task<IActionResult> AddRange(
|
||||||
[FromRoute] Guid idDiscriminator,
|
[FromRoute] Guid idDiscriminator,
|
||||||
[FromBody] IEnumerable<ChangeLogValuesDto> dtos,
|
[FromBody] IEnumerable<DataWithWellDepthAndSectionDto> dtos,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var userId = User.GetUserId<Guid>();
|
var userId = User.GetUserId<Guid>();
|
||||||
@ -70,7 +69,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
|
|||||||
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> ClearAndAddRange(
|
public async Task<IActionResult> ClearAndAddRange(
|
||||||
[FromRoute] Guid idDiscriminator,
|
[FromRoute] Guid idDiscriminator,
|
||||||
[FromBody] IEnumerable<ChangeLogValuesDto> dtos,
|
[FromBody] IEnumerable<DataWithWellDepthAndSectionDto> dtos,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var userId = User.GetUserId<Guid>();
|
var userId = User.GetUserId<Guid>();
|
||||||
@ -81,7 +80,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
|
|||||||
[HttpPut]
|
[HttpPut]
|
||||||
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> Update(
|
public async Task<IActionResult> Update(
|
||||||
ChangeLogValuesDto dto,
|
DataWithWellDepthAndSectionDto dto,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var userId = User.GetUserId<Guid>();
|
var userId = User.GetUserId<Guid>();
|
||||||
@ -93,7 +92,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
|
|||||||
[HttpPut("range")]
|
[HttpPut("range")]
|
||||||
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> UpdateRange(
|
public async Task<IActionResult> UpdateRange(
|
||||||
IEnumerable<ChangeLogValuesDto> dtos,
|
IEnumerable<DataWithWellDepthAndSectionDto> dtos,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var userId = User.GetUserId<Guid>();
|
var userId = User.GetUserId<Guid>();
|
||||||
@ -103,27 +102,29 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{idDiscriminator}")]
|
[HttpGet("{idDiscriminator}")]
|
||||||
[ProducesResponseType(typeof(PaginationContainer<ChangeLogValuesDto>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(PaginationContainer<DataWithWellDepthAndSectionDto>), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> GetCurrent(
|
public async Task<IActionResult> GetCurrent(
|
||||||
[FromRoute] Guid idDiscriminator,
|
[FromRoute] Guid idDiscriminator,
|
||||||
|
[FromQuery] SectionPartRequest filterRequest,
|
||||||
[FromQuery] PaginationRequest paginationRequest,
|
[FromQuery] PaginationRequest paginationRequest,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var moment = new DateTimeOffset(3000, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
var moment = new DateTimeOffset(3000, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
||||||
var result = await repository.GetByDate(idDiscriminator, moment, paginationRequest, token);
|
var result = await repository.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token);
|
||||||
|
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("moment/{idDiscriminator}")]
|
[HttpGet("moment/{idDiscriminator}")]
|
||||||
[ProducesResponseType(typeof(PaginationContainer<ChangeLogValuesDto>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(PaginationContainer<DataWithWellDepthAndSectionDto>), (int)HttpStatusCode.OK)]
|
||||||
public async Task<IActionResult> GetByDate(
|
public async Task<IActionResult> GetByDate(
|
||||||
[FromRoute] Guid idDiscriminator,
|
[FromRoute] Guid idDiscriminator,
|
||||||
DateTimeOffset moment,
|
DateTimeOffset moment,
|
||||||
|
[FromQuery] SectionPartRequest filterRequest,
|
||||||
[FromQuery] PaginationRequest paginationRequest,
|
[FromQuery] PaginationRequest paginationRequest,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var result = await repository.GetByDate(idDiscriminator, moment, paginationRequest, token);
|
var result = await repository.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token);
|
||||||
|
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
@ -153,9 +154,9 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("part/{idDiscriminator}")]
|
[HttpGet("part/{idDiscriminator}")]
|
||||||
[ProducesResponseType(typeof(IEnumerable<ChangeLogValuesDto>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(IEnumerable<DataWithWellDepthAndSectionDto>), (int)HttpStatusCode.OK)]
|
||||||
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
||||||
public async Task<ActionResult<IEnumerable<ChangeLogValuesDto>>> GetPart([FromRoute] Guid idDiscriminator, DateTimeOffset dateBegin, int take = 86400, CancellationToken token = default)
|
public async Task<ActionResult<IEnumerable<DataWithWellDepthAndSectionDto>>> GetPart([FromRoute] Guid idDiscriminator, DateTimeOffset dateBegin, int take = 86400, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var result = await repository.GetGtDate(idDiscriminator, dateBegin, token);
|
var result = await repository.GetGtDate(idDiscriminator, dateBegin, token);
|
||||||
|
|
||||||
|
20
DD.Persistence.API/Controllers/DataSaubController.cs
Normal file
20
DD.Persistence.API/Controllers/DataSaubController.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using DD.Persistence.Repositories;
|
||||||
|
|
||||||
|
namespace DD.Persistence.API.Controllers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Работа с временными данными
|
||||||
|
/// </summary>
|
||||||
|
[ApiController]
|
||||||
|
[Authorize]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class DataSaubController : TimeSeriesController<DataSaubDto>
|
||||||
|
{
|
||||||
|
public DataSaubController(ITimeSeriesDataRepository<DataSaubDto> timeSeriesDataRepository) : base(timeSeriesDataRepository)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,6 @@ using DD.Persistence.Models;
|
|||||||
using DD.Persistence.Repositories;
|
using DD.Persistence.Repositories;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.API.Controllers;
|
namespace DD.Persistence.API.Controllers;
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ using DD.Persistence.Models;
|
|||||||
using DD.Persistence.Models.Requests;
|
using DD.Persistence.Models.Requests;
|
||||||
using DD.Persistence.Repositories;
|
using DD.Persistence.Repositories;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.API.Controllers;
|
namespace DD.Persistence.API.Controllers;
|
||||||
|
|
||||||
|
76
DD.Persistence.API/Controllers/TimeSeriesController.cs
Normal file
76
DD.Persistence.API/Controllers/TimeSeriesController.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using DD.Persistence.Repositories;
|
||||||
|
|
||||||
|
namespace DD.Persistence.API.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Authorize]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class TimeSeriesController<TDto> : ControllerBase, ITimeSeriesDataApi<TDto>
|
||||||
|
where TDto : class, ITimeSeriesAbstractDto, new()
|
||||||
|
{
|
||||||
|
private readonly ITimeSeriesDataRepository<TDto> timeSeriesDataRepository;
|
||||||
|
|
||||||
|
public TimeSeriesController(ITimeSeriesDataRepository<TDto> timeSeriesDataRepository)
|
||||||
|
{
|
||||||
|
this.timeSeriesDataRepository = timeSeriesDataRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить список объектов, удовлетворяющий диапазону дат
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dateBegin"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
public async Task<IActionResult> Get(DateTimeOffset dateBegin, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await timeSeriesDataRepository.GetGtDate(dateBegin, token);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить диапазон дат, для которых есть данные в репозитории
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("datesRange")]
|
||||||
|
public async Task<IActionResult> GetDatesRange(CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await timeSeriesDataRepository.GetDatesRange(token);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить список объектов с прореживанием, удовлетворяющий диапазону дат
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dateBegin"></param>
|
||||||
|
/// <param name="intervalSec"></param>
|
||||||
|
/// <param name="approxPointsCount"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("resampled")]
|
||||||
|
public async Task<IActionResult> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var result = await timeSeriesDataRepository.GetResampledData(dateBegin, intervalSec, approxPointsCount, token);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Добавить записи
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dtos"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> AddRange(IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await timeSeriesDataRepository.AddRange(dtos, token);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
104
DD.Persistence.API/Controllers/TimestampedSetController.cs
Normal file
104
DD.Persistence.API/Controllers/TimestampedSetController.cs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using DD.Persistence.Repositories;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace DD.Persistence.API.Controllers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Хранение наборов данных с отметкой времени.
|
||||||
|
/// Не оптимизировано под большие данные.
|
||||||
|
/// </summary>
|
||||||
|
[ApiController]
|
||||||
|
[Authorize]
|
||||||
|
[Route("api/[controller]/{idDiscriminator}")]
|
||||||
|
public class TimestampedSetController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ITimestampedSetRepository repository;
|
||||||
|
|
||||||
|
public TimestampedSetController(ITimestampedSetRepository repository)
|
||||||
|
{
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Записать новые данные
|
||||||
|
/// Предполагается что данные с одним дискриминатором имеют одинаковую структуру
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
|
||||||
|
/// <param name="sets"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns>кол-во затронутых записей</returns>
|
||||||
|
[HttpPost]
|
||||||
|
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
|
||||||
|
public async Task<IActionResult> AddRange([FromRoute] Guid idDiscriminator, [FromBody] IEnumerable<TimestampedSetDto> sets, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await repository.AddRange(idDiscriminator, sets, token);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получение данных с фильтрацией. Значение фильтра null - отключен
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
|
||||||
|
/// <param name="geTimestamp">Фильтр позднее даты</param>
|
||||||
|
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
|
||||||
|
/// <param name="skip"></param>
|
||||||
|
/// <param name="take"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns>Фильтрованный набор данных с сортировкой по отметке времени</returns>
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType(typeof(IEnumerable<TimestampedSetDto>), (int)HttpStatusCode.OK)]
|
||||||
|
public async Task<IActionResult> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, [FromQuery] IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await repository.Get(idDiscriminator, geTimestamp, columnNames, skip, take, token);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить последние данные
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
|
||||||
|
/// <param name="columnNames">Фильтр свойств набора. Можно запросить только некоторые свойства из набора</param>
|
||||||
|
/// <param name="take"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns>Фильтрованный набор данных с сортировкой по отметке времени</returns>
|
||||||
|
[HttpGet("last")]
|
||||||
|
[ProducesResponseType(typeof(IEnumerable<TimestampedSetDto>), (int)HttpStatusCode.OK)]
|
||||||
|
public async Task<IActionResult> GetLast(Guid idDiscriminator, [FromQuery] IEnumerable<string>? columnNames, int take, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await repository.GetLast(idDiscriminator, columnNames, take, token);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Диапазон дат за которые есть данные
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns>Дата первой и последней записи</returns>
|
||||||
|
[HttpGet("datesRange")]
|
||||||
|
[ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)]
|
||||||
|
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
||||||
|
public async Task<IActionResult> GetDatesRange(Guid idDiscriminator, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await repository.GetDatesRange(idDiscriminator, token);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Количество записей по указанному набору в БД. Для пагинации.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator">Дискриминатор (идентификатор) набора</param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("count")]
|
||||||
|
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
|
||||||
|
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
||||||
|
public async Task<IActionResult> Count(Guid idDiscriminator, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await repository.Count(idDiscriminator, token);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
}
|
@ -1,153 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
namespace DD.Persistence.API.Controllers;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Хранение наборов данных с отметкой времени.
|
|
||||||
/// </summary>
|
|
||||||
[ApiController]
|
|
||||||
[Authorize]
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
public class TimestampedValuesController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ITimestampedValuesService timestampedValuesService;
|
|
||||||
private readonly ITimestampedValuesRepository timestampedValuesRepository;
|
|
||||||
public TimestampedValuesController(ITimestampedValuesService repository, ITimestampedValuesRepository timestampedValuesRepository)
|
|
||||||
{
|
|
||||||
this.timestampedValuesService = repository;
|
|
||||||
this.timestampedValuesRepository = timestampedValuesRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Записать новые данные.
|
|
||||||
/// Предполагается что данные с одним дискриминатором имеют одинаковую структуру
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="dtos"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
[HttpPost("{discriminatorId}")]
|
|
||||||
[ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)]
|
|
||||||
public async Task<IActionResult> AddRange([FromRoute] Guid discriminatorId, [FromBody] IEnumerable<TimestampedValuesDto> dtos, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await timestampedValuesService.AddRange(discriminatorId, dtos, token);
|
|
||||||
|
|
||||||
return CreatedAtAction(nameof(AddRange), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение данных с фильтрацией. Значение фильтра null - отключен
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorIds">Набор дискриминаторов</param>
|
|
||||||
/// <param name="timestampBegin">Фильтр позднее даты</param>
|
|
||||||
/// <param name="columnNames">Фильтр свойств набора</param>
|
|
||||||
/// <param name="skip"></param>
|
|
||||||
/// <param name="take"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
[HttpGet]
|
|
||||||
[ProducesResponseType(typeof(IEnumerable<TimestampedValuesDto>), (int)HttpStatusCode.OK)]
|
|
||||||
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
|
||||||
public async Task<ActionResult<IEnumerable<TimestampedValuesDto>>> Get([FromQuery] IEnumerable<Guid> 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные, начиная с заданной отметки времени
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="timestampBegin">Фильтр позднее даты</param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
[HttpGet("{discriminatorId}/gtdate")]
|
|
||||||
[ProducesResponseType(typeof(IEnumerable<TimestampedValuesDto>), (int)HttpStatusCode.OK)]
|
|
||||||
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
|
||||||
public async Task<ActionResult<IEnumerable<TimestampedValuesDto>>> GetGtDate([FromRoute] Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await timestampedValuesService.GetGtDate(discriminatorId, timestampBegin, token);
|
|
||||||
|
|
||||||
return result.Any() ? Ok(result) : NoContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные c начала
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="take"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
[HttpGet("{discriminatorId}/first")]
|
|
||||||
[ProducesResponseType(typeof(IEnumerable<TimestampedValuesDto>), (int)HttpStatusCode.OK)]
|
|
||||||
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
|
||||||
public async Task<ActionResult<IEnumerable<TimestampedValuesDto>>> GetFirst([FromRoute] Guid discriminatorId, int take, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await timestampedValuesService.GetFirst(discriminatorId, take, token);
|
|
||||||
|
|
||||||
return result.Any() ? Ok(result) : NoContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные c конца
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="take"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
[HttpGet("{discriminatorId}/last")]
|
|
||||||
[ProducesResponseType(typeof(IEnumerable<TimestampedValuesDto>), (int)HttpStatusCode.OK)]
|
|
||||||
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
|
||||||
public async Task<ActionResult<IEnumerable<TimestampedValuesDto>>> GetLast([FromRoute] Guid discriminatorId, int take, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await timestampedValuesService.GetLast(discriminatorId, take, token);
|
|
||||||
|
|
||||||
return result.Any() ? Ok(result) : NoContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить список объектов с прореживанием, удовлетворяющий диапазону дат
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="timestampBegin">Фильтр позднее даты</param>
|
|
||||||
/// <param name="intervalSec"></param>
|
|
||||||
/// <param name="approxPointsCount"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
[HttpGet("{discriminatorId}/resampled")]
|
|
||||||
[ProducesResponseType(typeof(IEnumerable<TimestampedValuesDto>), (int)HttpStatusCode.OK)]
|
|
||||||
[ProducesResponseType((int)HttpStatusCode.NoContent)]
|
|
||||||
public async Task<ActionResult<IEnumerable<TimestampedValuesDto>>> GetResampledData([FromRoute] Guid discriminatorId, DateTimeOffset timestampBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default)
|
|
||||||
{
|
|
||||||
var result = await timestampedValuesService.GetResampledData(discriminatorId, timestampBegin, intervalSec, approxPointsCount, token);
|
|
||||||
|
|
||||||
return result.Any() ? Ok(result) : NoContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить количество записей по указанному набору в БД. Для пагинации
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
[HttpGet("{discriminatorId}/count")]
|
|
||||||
public async Task<ActionResult<int>> Count([FromRoute] Guid discriminatorId, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await timestampedValuesRepository.Count(discriminatorId, token);
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить диапазон дат, в пределах которых хранятся даные
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
[HttpGet("{discriminatorId}/datesRange")]
|
|
||||||
public async Task<ActionResult<DatesRangeDto>> GetDatesRange([FromRoute] Guid discriminatorId, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await timestampedValuesRepository.GetDatesRange(discriminatorId, token);
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Services.Interfaces;
|
using DD.Persistence.Services.Interfaces;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.API.Controllers;
|
namespace DD.Persistence.API.Controllers;
|
||||||
|
|
||||||
|
@ -53,7 +53,6 @@ public static class DependencyInjection
|
|||||||
public static void AddServices(this IServiceCollection services)
|
public static void AddServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddTransient<IWitsDataService, WitsDataService>();
|
services.AddTransient<IWitsDataService, WitsDataService>();
|
||||||
services.AddTransient<ITimestampedValuesService, TimestampedValuesService>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Authentication
|
#region Authentication
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using DD.Persistence.Database.Model;
|
using DD.Persistence.Database.Model;
|
||||||
using DD.Persistence.Database.Postgres.Extensions;
|
using DD.Persistence.Database.Postgres;
|
||||||
using DD.Persistence.Repository;
|
using DD.Persistence.Repository;
|
||||||
|
|
||||||
namespace DD.Persistence.API;
|
namespace DD.Persistence.API;
|
||||||
@ -59,6 +59,7 @@ public class Startup
|
|||||||
|
|
||||||
var context = provider.GetRequiredService<PersistencePostgresContext>();
|
var context = provider.GetRequiredService<PersistencePostgresContext>();
|
||||||
context.Database.EnsureCreatedAndMigrated();
|
context.Database.EnsureCreatedAndMigrated();
|
||||||
context.Database.AddPartitioning();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,50 +1,24 @@
|
|||||||
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||||
USER app
|
USER app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
EXPOSE 8081
|
EXPOSE 8081
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
ARG BUILD_CONFIGURATION=Release
|
ARG BUILD_CONFIGURATION=Release
|
||||||
ARG PUBLISHERPASSWORD
|
|
||||||
|
|
||||||
# 1. Настраиваем рабочую директорию
|
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
|
||||||
# 2. Добавляем приватный NuGet-репозиторий
|
|
||||||
#RUN dotnet nuget add source \
|
|
||||||
#--name gitea \
|
|
||||||
#--username publisher \
|
|
||||||
#--password $PUBLISHERPASSWORD \
|
|
||||||
#--store-password-in-clear-text \
|
|
||||||
#https://git.ddrilling.ru/api/packages/DDrilling/nuget/index.json
|
|
||||||
|
|
||||||
# 3. Копируем csproj-файлы и восстанавливаем пакеты
|
|
||||||
COPY ["DD.Persistence.App/DD.Persistence.App.csproj", "DD.Persistence.App/"]
|
COPY ["DD.Persistence.App/DD.Persistence.App.csproj", "DD.Persistence.App/"]
|
||||||
COPY ["DD.Persistence.API/DD.Persistence.API.csproj", "DD.Persistence.API/"]
|
|
||||||
COPY ["DD.Persistence/DD.Persistence.csproj", "DD.Persistence/"]
|
|
||||||
COPY ["DD.Persistence.Database/DD.Persistence.Database.csproj", "DD.Persistence.Database/"]
|
|
||||||
COPY ["DD.Persistence.Database.Postgres/DD.Persistence.Database.Postgres.csproj", "DD.Persistence.Database.Postgres/"]
|
|
||||||
COPY ["DD.Persistence.Models/DD.Persistence.Models.csproj", "DD.Persistence.Models/"]
|
|
||||||
COPY ["DD.Persistence.Repository/DD.Persistence.Repository.csproj", "DD.Persistence.Repository/"]
|
|
||||||
|
|
||||||
RUN dotnet restore "./DD.Persistence.App/DD.Persistence.App.csproj"
|
RUN dotnet restore "./DD.Persistence.App/DD.Persistence.App.csproj"
|
||||||
|
|
||||||
# 4. Копируем *всё* оставшееся (код и т. п.)
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# 5. Собираем
|
|
||||||
WORKDIR "/src/DD.Persistence.App"
|
WORKDIR "/src/DD.Persistence.App"
|
||||||
RUN dotnet build "./DD.Persistence.App.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
RUN dotnet build "./DD.Persistence.App.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
||||||
|
|
||||||
# ---------- Публикация приложения ----------
|
|
||||||
FROM build AS publish
|
FROM build AS publish
|
||||||
ARG BUILD_CONFIGURATION=Release
|
ARG BUILD_CONFIGURATION=Release
|
||||||
RUN dotnet publish "./DD.Persistence.App.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
|
RUN dotnet publish "./DD.Persistence.App.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
# ---------- Финальный образ с рантаймом ----------
|
|
||||||
FROM base AS final
|
FROM base AS final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=publish /app/publish .
|
COPY --from=publish /app/publish .
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"DbConnection": {
|
"DbConnection": {
|
||||||
"Host": "postgres",
|
"Host": "localhost",
|
||||||
"Port": 5432,
|
"Port": 5432,
|
||||||
"Database": "persistence",
|
"Database": "persistence",
|
||||||
"Username": "postgres",
|
"Username": "postgres",
|
||||||
|
@ -4,22 +4,18 @@ using DD.Persistence.Client.Clients.Interfaces;
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Requests;
|
using DD.Persistence.Models.Requests;
|
||||||
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients;
|
namespace DD.Persistence.Client.Clients;
|
||||||
/// <inheritdoc/>
|
|
||||||
public class ChangeLogClient : BaseClient, IChangeLogClient
|
public class ChangeLogClient : BaseClient, IChangeLogClient
|
||||||
{
|
{
|
||||||
private readonly IRefitChangeLogClient refitChangeLogClient;
|
private readonly IRefitChangeLogClient refitChangeLogClient;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public ChangeLogClient(IRefitClientFactory<IRefitChangeLogClient> refitClientFactory, ILogger<ChangeLogClient> logger) : base(logger)
|
public ChangeLogClient(IRefitClientFactory<IRefitChangeLogClient> refitClientFactory, ILogger<ChangeLogClient> logger) : base(logger)
|
||||||
{
|
{
|
||||||
this.refitChangeLogClient = refitClientFactory.Create();
|
this.refitChangeLogClient = refitClientFactory.Create();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
public async Task<int> ClearAndAddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
|
||||||
public async Task<int> ClearAndAddRange(Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token)
|
|
||||||
{
|
{
|
||||||
var result = await ExecuteGetResponse(
|
var result = await ExecuteGetResponse(
|
||||||
async () => await refitChangeLogClient.ClearAndAddRange(idDiscriminator, dtos, token), token);
|
async () => await refitChangeLogClient.ClearAndAddRange(idDiscriminator, dtos, token), token);
|
||||||
@ -27,17 +23,15 @@ public class ChangeLogClient : BaseClient, IChangeLogClient
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
public async Task<PaginationContainer<DataWithWellDepthAndSectionDto>> GetByDate(Guid idDiscriminator, DateTimeOffset moment,
|
||||||
public async Task<PaginationContainer<ChangeLogValuesDto>> GetByDate(Guid idDiscriminator, DateTimeOffset moment,
|
SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token)
|
||||||
PaginationRequest paginationRequest, CancellationToken token)
|
|
||||||
{
|
{
|
||||||
var result = await ExecuteGetResponse(
|
var result = await ExecuteGetResponse(
|
||||||
async () => await refitChangeLogClient.GetByDate(idDiscriminator, moment, paginationRequest, token), token);
|
async () => await refitChangeLogClient.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token), token);
|
||||||
|
|
||||||
return result!;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
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 result = await ExecuteGetResponse(
|
var result = await ExecuteGetResponse(
|
||||||
@ -46,8 +40,7 @@ public class ChangeLogClient : BaseClient, IChangeLogClient
|
|||||||
return result!;
|
return result!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
public async Task<int> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token)
|
||||||
public async Task<int> Add(Guid idDiscriminator, ChangeLogValuesDto dto, CancellationToken token)
|
|
||||||
{
|
{
|
||||||
var result = await ExecutePostResponse(
|
var result = await ExecutePostResponse(
|
||||||
async () => await refitChangeLogClient.Add(idDiscriminator, dto, token), token);
|
async () => await refitChangeLogClient.Add(idDiscriminator, dto, token), token);
|
||||||
@ -55,8 +48,7 @@ public class ChangeLogClient : BaseClient, IChangeLogClient
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
public async Task<int> AddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
|
||||||
public async Task<int> AddRange(Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token)
|
|
||||||
{
|
{
|
||||||
var result = await ExecutePostResponse(
|
var result = await ExecutePostResponse(
|
||||||
async () => await refitChangeLogClient.AddRange(idDiscriminator, dtos, token), token);
|
async () => await refitChangeLogClient.AddRange(idDiscriminator, dtos, token), token);
|
||||||
@ -64,8 +56,7 @@ public class ChangeLogClient : BaseClient, IChangeLogClient
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
public async Task<int> Update(DataWithWellDepthAndSectionDto dto, CancellationToken token)
|
||||||
public async Task<int> Update(ChangeLogValuesDto dto, CancellationToken token)
|
|
||||||
{
|
{
|
||||||
var result = await ExecutePostResponse(
|
var result = await ExecutePostResponse(
|
||||||
async () => await refitChangeLogClient.Update(dto, token), token);
|
async () => await refitChangeLogClient.Update(dto, token), token);
|
||||||
@ -73,8 +64,7 @@ public class ChangeLogClient : BaseClient, IChangeLogClient
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
public async Task<int> UpdateRange(IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
|
||||||
public async Task<int> UpdateRange(IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token)
|
|
||||||
{
|
{
|
||||||
var result = await ExecutePostResponse(
|
var result = await ExecutePostResponse(
|
||||||
async () => await refitChangeLogClient.UpdateRange(dtos, token), token);
|
async () => await refitChangeLogClient.UpdateRange(dtos, token), token);
|
||||||
@ -82,7 +72,6 @@ public class ChangeLogClient : BaseClient, IChangeLogClient
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<int> Delete(Guid id, CancellationToken token)
|
public async Task<int> Delete(Guid id, CancellationToken token)
|
||||||
{
|
{
|
||||||
var result = await ExecutePostResponse(
|
var result = await ExecutePostResponse(
|
||||||
@ -91,7 +80,6 @@ public class ChangeLogClient : BaseClient, IChangeLogClient
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<int> DeleteRange(IEnumerable<Guid> ids, CancellationToken token)
|
public async Task<int> DeleteRange(IEnumerable<Guid> ids, CancellationToken token)
|
||||||
{
|
{
|
||||||
var result = await ExecutePostResponse(
|
var result = await ExecutePostResponse(
|
||||||
@ -100,7 +88,6 @@ public class ChangeLogClient : BaseClient, IChangeLogClient
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token)
|
public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token)
|
||||||
{
|
{
|
||||||
var result = await ExecuteGetResponse(
|
var result = await ExecuteGetResponse(
|
||||||
@ -109,7 +96,6 @@ public class ChangeLogClient : BaseClient, IChangeLogClient
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
refitChangeLogClient.Dispose();
|
refitChangeLogClient.Dispose();
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using DD.Persistence.Models.Requests;
|
using DD.Persistence.Models.Requests;
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients.Interfaces;
|
namespace DD.Persistence.Client.Clients.Interfaces;
|
||||||
@ -16,7 +15,7 @@ public interface IChangeLogClient : IDisposable
|
|||||||
/// <param name="dto"></param>
|
/// <param name="dto"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> Add(Guid idDiscriminator, ChangeLogValuesDto dto, CancellationToken token);
|
Task<int> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавить несколько записей
|
/// Добавить несколько записей
|
||||||
@ -25,7 +24,7 @@ public interface IChangeLogClient : IDisposable
|
|||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> AddRange(Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token);
|
Task<int> AddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Импорт с заменой: удаление старых строк и добавление новых
|
/// Импорт с заменой: удаление старых строк и добавление новых
|
||||||
@ -34,7 +33,7 @@ public interface IChangeLogClient : IDisposable
|
|||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> ClearAndAddRange(Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token);
|
Task<int> ClearAndAddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Удалить одну запись
|
/// Удалить одну запись
|
||||||
@ -57,10 +56,11 @@ public interface IChangeLogClient : IDisposable
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idDiscriminator"></param>
|
/// <param name="idDiscriminator"></param>
|
||||||
/// <param name="moment"></param>
|
/// <param name="moment"></param>
|
||||||
|
/// <param name="filterRequest"></param>
|
||||||
/// <param name="paginationRequest"></param>
|
/// <param name="paginationRequest"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<PaginationContainer<ChangeLogValuesDto>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, PaginationRequest paginationRequest, CancellationToken token);
|
Task<PaginationContainer<DataWithWellDepthAndSectionDto>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение исторических данных за определенный период времени
|
/// Получение исторических данных за определенный период времени
|
||||||
@ -86,7 +86,7 @@ public interface IChangeLogClient : IDisposable
|
|||||||
/// <param name="dto"></param>
|
/// <param name="dto"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> Update(ChangeLogValuesDto dto, CancellationToken token);
|
Task<int> Update(DataWithWellDepthAndSectionDto dto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обновить несколько записей
|
/// Обновить несколько записей
|
||||||
@ -94,5 +94,5 @@ public interface IChangeLogClient : IDisposable
|
|||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> UpdateRange(IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token);
|
Task<int> UpdateRange(IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients.Interfaces;
|
namespace DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using DD.Persistence.Models.Requests;
|
using DD.Persistence.Models.Requests;
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients.Interfaces;
|
namespace DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
using DD.Persistence.Models;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Клиент для работы с временными данными
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TDto"></typeparam>
|
||||||
|
public interface ITimeSeriesClient<TDto> : IDisposable where TDto : class, ITimeSeriesAbstractDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Добавление записей
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dtos"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить список объектов, удовлетворяющий диапазону дат
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dateBegin"></param>
|
||||||
|
/// <param name="dateEnd"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<TDto>> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить диапазон дат, для которых есть данные в репозитории
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<DatesRangeDto?> GetDatesRange(CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить список объектов с прореживанием, удовлетворяющий диапазону дат
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dateBegin"></param>
|
||||||
|
/// <param name="intervalSec"></param>
|
||||||
|
/// <param name="approxPointsCount"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<TDto>> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default);
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
using DD.Persistence.Models;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Клиент для работы с репозиторием для хранения разных наборов данных рядов.
|
||||||
|
/// idDiscriminator - идентифицирует конкретный набор данных, прим.: циклы измерения АСИБР, или отчет о DrillTest.
|
||||||
|
/// idDiscriminator формируют клиенты и только им известно что они обозначают.
|
||||||
|
/// Так как данные приходят редко, то их прореживания для построения графиков не предусмотрено.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITimestampedSetClient : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Записать новые данные
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator"></param>
|
||||||
|
/// <param name="sets"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<int> AddRange(Guid idDiscriminator, IEnumerable<TimestampedSetDto> sets, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Количество записей по указанному набору в БД. Для пагинации
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<int> Count(Guid idDiscriminator, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получение данных с фильтрацией. Значение фильтра null - отключен
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator"></param>
|
||||||
|
/// <param name="geTimestamp"></param>
|
||||||
|
/// <param name="columnNames"></param>
|
||||||
|
/// <param name="skip"></param>
|
||||||
|
/// <param name="take"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получение данных с фильтрацией. Значение фильтра null - отключен
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator"></param>
|
||||||
|
/// <param name="geTimestamp"></param>
|
||||||
|
/// <param name="columnNames"></param>
|
||||||
|
/// <param name="skip"></param>
|
||||||
|
/// <param name="take"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<T>> Get<T>(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Диапазон дат за которые есть данные
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator"></param>
|
||||||
|
/// <param name="columnNames"></param>
|
||||||
|
/// <param name="take"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? columnNames, int take, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idDiscriminator"></param>
|
||||||
|
/// <param name="columnNames"></param>
|
||||||
|
/// <param name="take"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<T>> GetLast<T>(Guid idDiscriminator, IEnumerable<string>? columnNames, int take, CancellationToken token);
|
||||||
|
}
|
@ -1,106 +0,0 @@
|
|||||||
using DD.Persistence.Models;
|
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients.Interfaces;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Клиент для работы с наборами данных, имеющими отметку времени.
|
|
||||||
/// discriminatorId - идентифицирует конкретный набор данных, прим.: циклы измерения АСИБР, или отчет о DrillTest.
|
|
||||||
/// discriminatorId формируют клиенты и только им известно что они обозначают.
|
|
||||||
/// </summary>
|
|
||||||
public interface ITimestampedValuesClient : IDisposable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Записать новые данные
|
|
||||||
/// Предполагается что данные с одним дискриминатором имеют одинаковую структуру
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="dtos"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
Task<int> AddRange(Guid discriminatorId, IEnumerable<TimestampedValuesDto> dtos, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные с фильтрацией для нескольких систем. Значение фильтра null - отключен
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorIds">Набор дискриминаторов (идентификаторов)</param>
|
|
||||||
/// <param name="timestampBegin">Фильтр позднее даты</param>
|
|
||||||
/// <param name="columnNames">Фильтр свойств набора</param>
|
|
||||||
/// <param name="skip"></param>
|
|
||||||
/// <param name="take"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
Task<IEnumerable<TimestampedValuesDto>> Get(IEnumerable<Guid> discriminatorIds,
|
|
||||||
DateTimeOffset? timestampBegin,
|
|
||||||
IEnumerable<string>? columnNames,
|
|
||||||
int skip,
|
|
||||||
int take,
|
|
||||||
CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные с фильтрацией для нескольких систем. Значение фильтра null - отключен
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId"></param>
|
|
||||||
/// <param name="geTimestamp"></param>
|
|
||||||
/// <param name="columnNames">Фильтр свойств набора</param>
|
|
||||||
/// <param name="skip"></param>
|
|
||||||
/// <param name="take"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
Task<IEnumerable<T>> Get<T>(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные, начиная с заданной отметки времени
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="timestampBegin">Фильтр позднее даты</param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
Task<IEnumerable<TimestampedValuesDto>> GetGtDate(Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные с начала
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="take"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
Task<IEnumerable<TimestampedValuesDto>> GetFirst(Guid discriminatorId, int take, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные с конца
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="take"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
Task<IEnumerable<TimestampedValuesDto>> GetLast(Guid discriminatorId, int take, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные с прореживанием, удовлетворяющем диапазону дат
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="timestampBegin"></param>
|
|
||||||
/// <param name="intervalSec"></param>
|
|
||||||
/// <param name="approxPointsCount"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
Task<IEnumerable<TimestampedValuesDto>> GetResampledData(Guid discriminatorId, DateTimeOffset timestampBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Количество записей по указанному набору в БД. Для пагинации
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
Task<int> Count(Guid discriminatorId, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Диапазон дат, в пределах которых осуществляется хранение данных
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discriminatorId">Дискриминатор (идентификатор) набора</param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
Task<DatesRangeDto?> GetDatesRange(Guid discriminatorId, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T"></typeparam>
|
|
||||||
/// <param name="idDiscriminator"></param>
|
|
||||||
/// <param name="take"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<IEnumerable<T>> GetLast<T>(Guid idDiscriminator, int take, CancellationToken token);
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using Refit;
|
using Refit;
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients.Interfaces;
|
namespace DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
@ -1,78 +1,45 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using DD.Persistence.Models.Requests;
|
using DD.Persistence.Models.Requests;
|
||||||
using Refit;
|
using Refit;
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients.Interfaces.Refit;
|
namespace DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Refit интерфейс для IRefitChangeLogClient
|
|
||||||
/// </summary>
|
|
||||||
public interface IRefitChangeLogClient : IRefitClient, IDisposable
|
public interface IRefitChangeLogClient : IRefitClient, IDisposable
|
||||||
{
|
{
|
||||||
private const string BaseRoute = "/api/ChangeLog";
|
private const string BaseRoute = "/api/ChangeLog";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Импорт с заменой: удаление старых строк и добавление новых
|
|
||||||
/// </summary>
|
|
||||||
[Post($"{BaseRoute}/replace/{{idDiscriminator}}")]
|
[Post($"{BaseRoute}/replace/{{idDiscriminator}}")]
|
||||||
Task<IApiResponse<int>> ClearAndAddRange(Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token);
|
Task<IApiResponse<int>> ClearAndAddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение актуальных данных на определенную дату (с пагинацией)
|
|
||||||
/// </summary>
|
|
||||||
[Get($"{BaseRoute}/moment/{{idDiscriminator}}")]
|
[Get($"{BaseRoute}/moment/{{idDiscriminator}}")]
|
||||||
Task<IApiResponse<PaginationContainer<ChangeLogValuesDto>>> GetByDate(
|
Task<IApiResponse<PaginationContainer<DataWithWellDepthAndSectionDto>>> GetByDate(
|
||||||
Guid idDiscriminator,
|
Guid idDiscriminator,
|
||||||
DateTimeOffset moment,
|
DateTimeOffset moment,
|
||||||
|
[Query] SectionPartRequest filterRequest,
|
||||||
[Query] PaginationRequest paginationRequest,
|
[Query] PaginationRequest paginationRequest,
|
||||||
CancellationToken token);
|
CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение исторических данных за определенный период времени
|
|
||||||
/// </summary>
|
|
||||||
[Get($"{BaseRoute}/history/{{idDiscriminator}}")]
|
[Get($"{BaseRoute}/history/{{idDiscriminator}}")]
|
||||||
Task<IApiResponse<IEnumerable<ChangeLogDto>>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
|
Task<IApiResponse<IEnumerable<ChangeLogDto>>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Добавить одну запись
|
|
||||||
/// </summary>
|
|
||||||
[Post($"{BaseRoute}/{{idDiscriminator}}")]
|
[Post($"{BaseRoute}/{{idDiscriminator}}")]
|
||||||
Task<IApiResponse<int>> Add(Guid idDiscriminator, ChangeLogValuesDto dto, CancellationToken token);
|
Task<IApiResponse<int>> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Добавить несколько записей
|
|
||||||
/// </summary>
|
|
||||||
[Post($"{BaseRoute}/range/{{idDiscriminator}}")]
|
[Post($"{BaseRoute}/range/{{idDiscriminator}}")]
|
||||||
Task<IApiResponse<int>> AddRange(Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token);
|
Task<IApiResponse<int>> AddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Обновить одну запись
|
|
||||||
/// </summary>
|
|
||||||
[Put($"{BaseRoute}")]
|
[Put($"{BaseRoute}")]
|
||||||
Task<IApiResponse<int>> Update(ChangeLogValuesDto dto, CancellationToken token);
|
Task<IApiResponse<int>> Update(DataWithWellDepthAndSectionDto dto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Обновить несколько записей
|
|
||||||
/// </summary>
|
|
||||||
[Put($"{BaseRoute}/range")]
|
[Put($"{BaseRoute}/range")]
|
||||||
Task<IApiResponse<int>> UpdateRange(IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token);
|
Task<IApiResponse<int>> UpdateRange(IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Удалить одну запись
|
|
||||||
/// </summary>
|
|
||||||
[Delete($"{BaseRoute}")]
|
[Delete($"{BaseRoute}")]
|
||||||
Task<IApiResponse<int>> Delete(Guid id, CancellationToken token);
|
Task<IApiResponse<int>> Delete(Guid id, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Удалить несколько записей
|
|
||||||
/// </summary>
|
|
||||||
[Delete($"{BaseRoute}/range")]
|
[Delete($"{BaseRoute}/range")]
|
||||||
Task<IApiResponse<int>> DeleteRange([Body] IEnumerable<Guid> ids, CancellationToken token);
|
Task<IApiResponse<int>> DeleteRange([Body] IEnumerable<Guid> ids, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени)
|
|
||||||
/// </summary>
|
|
||||||
[Get($"{BaseRoute}/datesRange/{{idDiscriminator}}")]
|
[Get($"{BaseRoute}/datesRange/{{idDiscriminator}}")]
|
||||||
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(Guid idDiscriminator, CancellationToken token);
|
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(Guid idDiscriminator, CancellationToken token);
|
||||||
|
|
||||||
|
@ -5,10 +5,6 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients.Interfaces.Refit;
|
namespace DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Базовый Refit интерфейс
|
|
||||||
/// </summary>
|
|
||||||
public interface IRefitClient
|
public interface IRefitClient
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using Refit;
|
using Refit;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Requests;
|
using DD.Persistence.Models.Requests;
|
||||||
using Refit;
|
using Refit;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients.Interfaces.Refit
|
namespace DD.Persistence.Client.Clients.Interfaces.Refit
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
using DD.Persistence.Models;
|
||||||
|
using Refit;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
|
public interface IRefitTimeSeriesClient<TDto> : IRefitClient, IDisposable
|
||||||
|
where TDto : class, ITimeSeriesAbstractDto
|
||||||
|
{
|
||||||
|
private const string BaseRoute = "/api/dataSaub";
|
||||||
|
|
||||||
|
[Post($"{BaseRoute}")]
|
||||||
|
Task<IApiResponse<int>> AddRange(IEnumerable<TDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
|
[Get($"{BaseRoute}")]
|
||||||
|
Task<IApiResponse<IEnumerable<TDto>>> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
|
||||||
|
|
||||||
|
[Get($"{BaseRoute}/resampled")]
|
||||||
|
Task<IApiResponse<IEnumerable<TDto>>> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default);
|
||||||
|
|
||||||
|
[Get($"{BaseRoute}/datesRange")]
|
||||||
|
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(CancellationToken token);
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
using DD.Persistence.Models;
|
||||||
|
using Refit;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
|
|
||||||
|
public interface IRefitTimestampedSetClient : IRefitClient, IDisposable
|
||||||
|
{
|
||||||
|
private const string baseUrl = "/api/TimestampedSet/{idDiscriminator}";
|
||||||
|
|
||||||
|
[Post(baseUrl)]
|
||||||
|
Task<IApiResponse<int>> AddRange(Guid idDiscriminator, IEnumerable<TimestampedSetDto> sets, CancellationToken token);
|
||||||
|
|
||||||
|
[Get(baseUrl)]
|
||||||
|
Task<IApiResponse<IEnumerable<TimestampedSetDto>>> Get(Guid idDiscriminator, [Query] DateTimeOffset? geTimestamp, [Query] IEnumerable<string>? columnNames, int skip, int take, CancellationToken token);
|
||||||
|
|
||||||
|
[Get($"{baseUrl}/last")]
|
||||||
|
Task<IApiResponse<IEnumerable<TimestampedSetDto>>> GetLast(Guid idDiscriminator, [Query] IEnumerable<string>? columnNames, int take, CancellationToken token);
|
||||||
|
|
||||||
|
[Get($"{baseUrl}/count")]
|
||||||
|
Task<IApiResponse<int>> Count(Guid idDiscriminator, CancellationToken token);
|
||||||
|
|
||||||
|
[Get($"{baseUrl}/datesRange")]
|
||||||
|
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(Guid idDiscriminator, CancellationToken token);
|
||||||
|
}
|
@ -1,66 +0,0 @@
|
|||||||
using DD.Persistence.Models;
|
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using Refit;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients.Interfaces.Refit;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Refit интерфейс для TimestampedValuesController
|
|
||||||
/// </summary>
|
|
||||||
public interface IRefitTimestampedValuesClient : IRefitClient, IDisposable
|
|
||||||
{
|
|
||||||
private const string baseUrl = "/api/TimestampedValues";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Записать новые данные
|
|
||||||
/// </summary>
|
|
||||||
[Post($"{baseUrl}/{{discriminatorId}}")]
|
|
||||||
Task<IApiResponse<int>> AddRange(Guid discriminatorId, IEnumerable<TimestampedValuesDto> dtos, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение данных с фильтрацией
|
|
||||||
/// </summary>
|
|
||||||
[Get($"{baseUrl}")]
|
|
||||||
Task<IApiResponse<IEnumerable<TimestampedValuesDto>>> Get([Query(CollectionFormat.Multi)] IEnumerable<Guid> discriminatorIds,
|
|
||||||
DateTimeOffset? timestampBegin,
|
|
||||||
[Query(CollectionFormat.Multi)] IEnumerable<string>? columnNames,
|
|
||||||
int skip,
|
|
||||||
int take,
|
|
||||||
CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные, начиная с заданной отметки времени
|
|
||||||
/// </summary>
|
|
||||||
[Get($"{baseUrl}/{{discriminatorId}}/gtdate")]
|
|
||||||
Task<IApiResponse<IEnumerable<TimestampedValuesDto>>> GetGtDate(Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные c начала
|
|
||||||
/// </summary>
|
|
||||||
[Get($"{baseUrl}/{{discriminatorId}}/first")]
|
|
||||||
Task<IApiResponse<IEnumerable<TimestampedValuesDto>>> GetFirst(Guid discriminatorId, int take, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить данные c конца
|
|
||||||
/// </summary>
|
|
||||||
[Get($"{baseUrl}/{{discriminatorId}}/last")]
|
|
||||||
Task<IApiResponse<IEnumerable<TimestampedValuesDto>>> GetLast(Guid discriminatorId, int take, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить список объектов с прореживанием, удовлетворяющий диапазону временных отметок
|
|
||||||
/// </summary>
|
|
||||||
[Get($"{baseUrl}/{{discriminatorId}}/resampled")]
|
|
||||||
Task<IApiResponse<IEnumerable<TimestampedValuesDto>>> GetResampledData(Guid discriminatorId, DateTimeOffset timestampBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить количество записей по указанному набору в БД. Для пагинации
|
|
||||||
/// </summary>
|
|
||||||
[Get($"{baseUrl}/{{discriminatorId}}/count")]
|
|
||||||
Task<IApiResponse<int>> Count(Guid discriminatorId, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить диапазон дат, в пределах которых хранятся даные
|
|
||||||
/// </summary>
|
|
||||||
[Get($"{baseUrl}/{{discriminatorId}}/datesRange")]
|
|
||||||
Task<IApiResponse<DatesRangeDto?>> GetDatesRange(Guid discriminatorId, CancellationToken token);
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using Refit;
|
using Refit;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients.Interfaces.Refit;
|
namespace DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
public interface IRefitWitsDataClient : IRefitClient, IDisposable
|
public interface IRefitWitsDataClient : IRefitClient, IDisposable
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using DD.Persistence.Client.Clients.Base;
|
using DD.Persistence.Client.Clients.Base;
|
||||||
using DD.Persistence.Client.Clients.Interfaces;
|
using DD.Persistence.Client.Clients.Interfaces;
|
||||||
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
@ -6,7 +6,6 @@ using DD.Persistence.Models;
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients;
|
namespace DD.Persistence.Client.Clients;
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ using DD.Persistence.Client.Clients.Interfaces;
|
|||||||
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Requests;
|
using DD.Persistence.Models.Requests;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients;
|
namespace DD.Persistence.Client.Clients;
|
||||||
|
|
||||||
|
55
DD.Persistence.Client/Clients/TimeSeriesClient.cs
Normal file
55
DD.Persistence.Client/Clients/TimeSeriesClient.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using DD.Persistence.Client.Clients.Base;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Client.Clients;
|
||||||
|
public class TimeSeriesClient<TDto> : BaseClient, ITimeSeriesClient<TDto> where TDto : class, ITimeSeriesAbstractDto
|
||||||
|
{
|
||||||
|
private readonly IRefitTimeSeriesClient<TDto> timeSeriesClient;
|
||||||
|
|
||||||
|
public TimeSeriesClient(IRefitClientFactory<IRefitTimeSeriesClient<TDto>> refitTechMessagesClientFactory, ILogger<TimeSeriesClient<TDto>> logger) : base(logger)
|
||||||
|
{
|
||||||
|
this.timeSeriesClient = refitTechMessagesClientFactory.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await ExecutePostResponse(
|
||||||
|
async () => await timeSeriesClient.AddRange(dtos, token), token);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TDto>> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await ExecuteGetResponse(
|
||||||
|
async () => await timeSeriesClient.Get(dateBegin, dateEnd, token), token);
|
||||||
|
|
||||||
|
return result!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TDto>> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var result = await ExecuteGetResponse(
|
||||||
|
async () => await timeSeriesClient.GetResampledData(dateBegin, intervalSec, approxPointsCount, token), token);
|
||||||
|
|
||||||
|
return result!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<DatesRangeDto?> GetDatesRange(CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await ExecuteGetResponse(
|
||||||
|
async () => await timeSeriesClient.GetDatesRange(token), token);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
timeSeriesClient.Dispose();
|
||||||
|
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
92
DD.Persistence.Client/Clients/TimestampedSetClient.cs
Normal file
92
DD.Persistence.Client/Clients/TimestampedSetClient.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using DD.Persistence.Client.Clients.Base;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Client.Clients;
|
||||||
|
public class TimestampedSetClient : BaseClient, ITimestampedSetClient
|
||||||
|
{
|
||||||
|
private readonly IRefitTimestampedSetClient refitTimestampedSetClient;
|
||||||
|
private readonly ConcurrentDictionary<Guid, TimestampedSetMapperBase> mapperCache = new();
|
||||||
|
public TimestampedSetClient(IRefitClientFactory<IRefitTimestampedSetClient> refitTimestampedSetClientFactory, ILogger<TimestampedSetClient> logger) : base(logger)
|
||||||
|
{
|
||||||
|
this.refitTimestampedSetClient = refitTimestampedSetClientFactory.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> AddRange(Guid idDiscriminator, IEnumerable<TimestampedSetDto> sets, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await ExecutePostResponse(
|
||||||
|
async () => await refitTimestampedSetClient.AddRange(idDiscriminator, sets, token), token);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await ExecuteGetResponse(
|
||||||
|
async () => await refitTimestampedSetClient.Get(idDiscriminator, geTimestamp, columnNames, skip, take, token), token);
|
||||||
|
|
||||||
|
return result!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? columnNames, int take, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await ExecuteGetResponse(
|
||||||
|
async () => await refitTimestampedSetClient.GetLast(idDiscriminator, columnNames, take, token), token);
|
||||||
|
|
||||||
|
return result!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> Count(Guid idDiscriminator, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await ExecuteGetResponse(
|
||||||
|
async () => await refitTimestampedSetClient.Count(idDiscriminator, token), token);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await ExecuteGetResponse(
|
||||||
|
async () => await refitTimestampedSetClient.GetDatesRange(idDiscriminator, token), token);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<T>> Get<T>(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
|
||||||
|
{
|
||||||
|
var data = await Get(idDiscriminator, geTimestamp, columnNames, skip, take, token);
|
||||||
|
var mapper = GetMapper<T>(idDiscriminator);
|
||||||
|
|
||||||
|
return data.Select(mapper.DeserializeTimeStampedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IEnumerable<T>> GetLast<T>(Guid idDiscriminator, IEnumerable<string>? columnNames, int take, CancellationToken token)
|
||||||
|
{
|
||||||
|
var data = await GetLast(idDiscriminator, columnNames, take, token);
|
||||||
|
var mapper = GetMapper<T>(idDiscriminator);
|
||||||
|
|
||||||
|
return data.Select(mapper.DeserializeTimeStampedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TimestampedSetMapper<T> GetMapper<T>(Guid idDiscriminator)
|
||||||
|
{
|
||||||
|
return (TimestampedSetMapper<T>)mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper<T>(idDiscriminator));
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
refitTimestampedSetClient.Dispose();
|
||||||
|
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,127 +0,0 @@
|
|||||||
using DD.Persistence.Client.Clients.Base;
|
|
||||||
using DD.Persistence.Client.Clients.Interfaces;
|
|
||||||
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
|
||||||
using DD.Persistence.Models;
|
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient
|
|
||||||
{
|
|
||||||
private readonly IRefitTimestampedValuesClient refitTimestampedSetClient;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public TimestampedValuesClient(IRefitClientFactory<IRefitTimestampedValuesClient> refitTimestampedSetClientFactory, ILogger<TimestampedValuesClient> logger) : base(logger)
|
|
||||||
{
|
|
||||||
this.refitTimestampedSetClient = refitTimestampedSetClientFactory.Create();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
private readonly ConcurrentDictionary<Guid, TimestampedSetMapperBase> mapperCache = new();
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<int> AddRange(Guid discriminatorId, IEnumerable<TimestampedValuesDto> sets, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await ExecutePostResponse(
|
|
||||||
async () => await refitTimestampedSetClient.AddRange(discriminatorId, sets, token), token);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<TimestampedValuesDto>> Get(IEnumerable<Guid> discriminatorIds, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await ExecuteGetResponse(
|
|
||||||
async () => await refitTimestampedSetClient.Get(discriminatorIds, geTimestamp, columnNames, skip, take, token), token);
|
|
||||||
return result!;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<T>> Get<T>(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
|
|
||||||
{
|
|
||||||
var data = await Get([discriminatorId], geTimestamp, columnNames, skip, take, token);
|
|
||||||
var mapper = GetMapper<T>(discriminatorId);
|
|
||||||
|
|
||||||
return data.Select(mapper.DeserializeTimeStampedData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<TimestampedValuesDto>> GetGtDate(Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await ExecuteGetResponse(
|
|
||||||
async () => await refitTimestampedSetClient.GetGtDate(discriminatorId, timestampBegin, token), token);
|
|
||||||
|
|
||||||
return result!;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<TimestampedValuesDto>> GetFirst(Guid discriminatorId, int take, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await ExecuteGetResponse(
|
|
||||||
async () => await refitTimestampedSetClient.GetFirst(discriminatorId, take, token), token);
|
|
||||||
|
|
||||||
return result!;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<TimestampedValuesDto>> GetLast(Guid discriminatorId, int take, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await ExecuteGetResponse(
|
|
||||||
async () => await refitTimestampedSetClient.GetLast(discriminatorId, take, token), token);
|
|
||||||
|
|
||||||
return result!;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<TimestampedValuesDto>> GetResampledData(Guid discriminatorId, DateTimeOffset dateBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default)
|
|
||||||
{
|
|
||||||
var result = await ExecuteGetResponse(
|
|
||||||
async () => await refitTimestampedSetClient.GetResampledData(discriminatorId, dateBegin, intervalSec, approxPointsCount, token), token);
|
|
||||||
|
|
||||||
return result!;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<int> Count(Guid discriminatorId, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await ExecuteGetResponse(
|
|
||||||
async () => await refitTimestampedSetClient.Count(discriminatorId, token), token);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<DatesRangeDto?> GetDatesRange(Guid discriminatorId, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await ExecuteGetResponse(
|
|
||||||
async () => await refitTimestampedSetClient.GetDatesRange(discriminatorId, token), token);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<IEnumerable<T>> GetLast<T>(Guid idDiscriminator, int take, CancellationToken token)
|
|
||||||
{
|
|
||||||
var data = await GetLast(idDiscriminator, take, token);
|
|
||||||
var mapper = GetMapper<T>(idDiscriminator);
|
|
||||||
|
|
||||||
return data.Select(mapper.DeserializeTimeStampedData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
private TimestampedSetMapper<T> GetMapper<T>(Guid idDiscriminator)
|
|
||||||
{
|
|
||||||
return (TimestampedSetMapper<T>)mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper<T>(idDiscriminator));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
refitTimestampedSetClient.Dispose();
|
|
||||||
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,6 @@ using DD.Persistence.Client.Clients.Base;
|
|||||||
using DD.Persistence.Client.Clients.Interfaces;
|
using DD.Persistence.Client.Clients.Interfaces;
|
||||||
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Client.Clients;
|
namespace DD.Persistence.Client.Clients;
|
||||||
public class WitsDataClient : BaseClient, IWitsDataClient
|
public class WitsDataClient : BaseClient, IWitsDataClient
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
<!--Наименование-->
|
<!--Наименование-->
|
||||||
<Title>DD.Persistence.Client</Title>
|
<Title>DD.Persistence.Client</Title>
|
||||||
<!--Версия пакета-->
|
<!--Версия пакета-->
|
||||||
<VersionPrefix>1.6.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1</VersionPrefix>
|
<VersionPrefix>1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1</VersionPrefix>
|
||||||
<!--Версия сборки-->
|
<!--Версия сборки-->
|
||||||
<AssemblyVersion>1.6.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1</AssemblyVersion>
|
<AssemblyVersion>1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1</AssemblyVersion>
|
||||||
<!--Id пакета-->
|
<!--Id пакета-->
|
||||||
<PackageId>DD.Persistence.Client</PackageId>
|
<PackageId>DD.Persistence.Client</PackageId>
|
||||||
|
|
||||||
@ -40,8 +40,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>1.6.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))</VersionPrefix>
|
<VersionPrefix>1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))</VersionPrefix>
|
||||||
<AssemblyVersion>1.6.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))</AssemblyVersion>
|
<AssemblyVersion>1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))</AssemblyVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -22,7 +22,8 @@ public static class DependencyInjection
|
|||||||
services.AddTransient<IDataSourceSystemClient, DataSourceSystemClient>();
|
services.AddTransient<IDataSourceSystemClient, DataSourceSystemClient>();
|
||||||
services.AddTransient<ISetpointClient, SetpointClient>();
|
services.AddTransient<ISetpointClient, SetpointClient>();
|
||||||
services.AddTransient<ITechMessagesClient, TechMessagesClient>();
|
services.AddTransient<ITechMessagesClient, TechMessagesClient>();
|
||||||
services.AddTransient<ITimestampedValuesClient, TimestampedValuesClient>();
|
services.AddTransient<ITimeSeriesClient<DataSaubDto>, TimeSeriesClient<DataSaubDto>>();
|
||||||
|
services.AddTransient<ITimestampedSetClient, TimestampedSetClient>();
|
||||||
services.AddTransient<IWitsDataClient, WitsDataClient>();
|
services.AddTransient<IWitsDataClient, WitsDataClient>();
|
||||||
|
|
||||||
services.AddSingleton<ISetpointConfigStorage, SetpointConfigStorage>(provider =>
|
services.AddSingleton<ISetpointConfigStorage, SetpointConfigStorage>(provider =>
|
||||||
|
@ -11,7 +11,8 @@ Persistence сервисом посредством обращения к кон
|
|||||||
## Список предоставляемых клиентов
|
## Список предоставляемых клиентов
|
||||||
- `ISetpointClient` - Клиент для работы с уставками
|
- `ISetpointClient` - Клиент для работы с уставками
|
||||||
- `ITechMessagesClient` - Клиент для работы с технологическими сообщениями
|
- `ITechMessagesClient` - Клиент для работы с технологическими сообщениями
|
||||||
- `ITimestampedValuesClient` - Клиент для работы с наборами данных, имеющими отметку времени
|
- `ITimeSeriesClient` - Клиент для работы с временными данными
|
||||||
|
- `ITimestampedSetClient` - Клиент для работы с данными с отметкой времени
|
||||||
- `IChangeLogClient` - Клиент для работы с записями ChangeLog
|
- `IChangeLogClient` - Клиент для работы с записями ChangeLog
|
||||||
- `IWitsDataClient` - Клиент для работы с параметрами Wits
|
- `IWitsDataClient` - Клиент для работы с параметрами Wits
|
||||||
- `IDataSourceSystemClient` - Клиент для работы с системами
|
- `IDataSourceSystemClient` - Клиент для работы с системами
|
||||||
|
@ -8,7 +8,7 @@ namespace DD.Persistence.Client;
|
|||||||
|
|
||||||
internal abstract class TimestampedSetMapperBase
|
internal abstract class TimestampedSetMapperBase
|
||||||
{
|
{
|
||||||
public abstract object Map(TimestampedValuesDto data);
|
public abstract object Map(TimestampedSetDto data);
|
||||||
|
|
||||||
}
|
}
|
||||||
internal class TimestampedSetMapper<T> : TimestampedSetMapperBase
|
internal class TimestampedSetMapper<T> : TimestampedSetMapperBase
|
||||||
@ -22,12 +22,12 @@ internal class TimestampedSetMapper<T> : TimestampedSetMapperBase
|
|||||||
IdDiscriminator = idDiscriminator;
|
IdDiscriminator = idDiscriminator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override object Map(TimestampedValuesDto data)
|
public override object Map(TimestampedSetDto data)
|
||||||
{
|
{
|
||||||
return DeserializeTimeStampedData(data)!;
|
return DeserializeTimeStampedData(data)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T DeserializeTimeStampedData(TimestampedValuesDto data)
|
public T DeserializeTimeStampedData(TimestampedSetDto data)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (entityType.IsValueType)
|
if (entityType.IsValueType)
|
||||||
@ -36,10 +36,10 @@ internal class TimestampedSetMapper<T> : TimestampedSetMapperBase
|
|||||||
return MapClass(data);
|
return MapClass(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private T MapClass(TimestampedValuesDto data)
|
private T MapClass(TimestampedSetDto data)
|
||||||
{
|
{
|
||||||
var entity = (T)RuntimeHelpers.GetUninitializedObject(typeof(T));
|
var entity = (T)RuntimeHelpers.GetUninitializedObject(typeof(T));
|
||||||
foreach (var (propertyName, value) in data.Values)
|
foreach (var (propertyName, value) in data.Set)
|
||||||
{
|
{
|
||||||
if (value is JsonElement jsonElement)
|
if (value is JsonElement jsonElement)
|
||||||
SetPropertyValueFromJson(ref entity, propertyName, jsonElement);
|
SetPropertyValueFromJson(ref entity, propertyName, jsonElement);
|
||||||
@ -48,11 +48,11 @@ internal class TimestampedSetMapper<T> : TimestampedSetMapperBase
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private T MapStruct(TimestampedValuesDto data)
|
private T MapStruct(TimestampedSetDto data)
|
||||||
{
|
{
|
||||||
var entity = Activator.CreateInstance<T>();
|
var entity = Activator.CreateInstance<T>();
|
||||||
object boxedEntity = entity!;
|
object boxedEntity = entity!;
|
||||||
foreach (var (propertyName, value) in data.Values)
|
foreach (var (propertyName, value) in data.Set)
|
||||||
{
|
{
|
||||||
if (value is JsonElement jsonElement)
|
if (value is JsonElement jsonElement)
|
||||||
SetPropertyValueForStructFromJson(ref boxedEntity, propertyName, jsonElement);
|
SetPropertyValueForStructFromJson(ref boxedEntity, propertyName, jsonElement);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Postgres.Extensions;
|
namespace DD.Persistence.Database.Postgres;
|
||||||
public static class EFExtensionsInitialization
|
public static class EFExtensionsInitialization
|
||||||
{
|
{
|
||||||
public static void EnsureCreatedAndMigrated(this DatabaseFacade db)
|
public static void EnsureCreatedAndMigrated(this DatabaseFacade db)
|
@ -1,44 +0,0 @@
|
|||||||
using DD.Persistence.Database.Entity;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Postgres.Extensions;
|
|
||||||
public static class EFExtensionsPartitioning
|
|
||||||
{
|
|
||||||
public static void AddPartitioning(this DatabaseFacade db)
|
|
||||||
{
|
|
||||||
db.CreateTimescaledbExtension();
|
|
||||||
db.AddParameterDataPartitioning();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CreateTimescaledbExtension(this DatabaseFacade db)
|
|
||||||
{
|
|
||||||
var sqlString = $"CREATE EXTENSION IF NOT EXISTS timescaledb;";
|
|
||||||
db.ExecuteSqlRaw(sqlString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Добавить партиционирование таблицы ParameterData (Wits - данные)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="db"></param>
|
|
||||||
private static void AddParameterDataPartitioning(this DatabaseFacade db)
|
|
||||||
{
|
|
||||||
var type = typeof(ParameterData);
|
|
||||||
var tableAttribute = type.GetCustomAttribute<TableAttribute>();
|
|
||||||
if (tableAttribute is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int sectionsNumber = 2;
|
|
||||||
const int chunkTimeInterval = 5;
|
|
||||||
var sqlString = $"SELECT create_hypertable('{tableAttribute.Name}'," +
|
|
||||||
$"'{nameof(ParameterData.Timestamp)}'," +
|
|
||||||
$"'{nameof(ParameterData.ParameterId)}'," +
|
|
||||||
$"{sectionsNumber}," +
|
|
||||||
$"chunk_time_interval => INTERVAL '{chunkTimeInterval} day');";
|
|
||||||
db.ExecuteSqlRaw(sqlString);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using System;
|
using System;
|
||||||
using System.Text.Json;
|
|
||||||
using DD.Persistence.Database.Model;
|
using DD.Persistence.Database.Model;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
@ -13,7 +12,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("20250122120353_Init")]
|
[Migration("20241220062251_Init")]
|
||||||
partial class Init
|
partial class Init
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -21,28 +20,11 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "9.0.0")
|
.HasAnnotation("ProductVersion", "8.0.10")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataScheme", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("DiscriminatorId")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid")
|
|
||||||
.HasComment("Идентификатор схемы данных");
|
|
||||||
|
|
||||||
b.Property<string>("PropNames")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("jsonb")
|
|
||||||
.HasComment("Наименования полей в порядке индексации");
|
|
||||||
|
|
||||||
b.HasKey("DiscriminatorId");
|
|
||||||
|
|
||||||
b.ToTable("data_scheme");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("SystemId")
|
b.Property<Guid>("SystemId")
|
||||||
@ -61,7 +43,7 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.HasKey("SystemId");
|
b.HasKey("SystemId");
|
||||||
|
|
||||||
b.ToTable("data_source_system");
|
b.ToTable("DataSourceSystem");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.ParameterData", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.ParameterData", b =>
|
||||||
@ -85,7 +67,7 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.HasKey("DiscriminatorId", "ParameterId", "Timestamp");
|
b.HasKey("DiscriminatorId", "ParameterId", "Timestamp");
|
||||||
|
|
||||||
b.ToTable("parameter_data");
|
b.ToTable("ParameterData");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b =>
|
||||||
@ -120,27 +102,30 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.HasIndex("SystemId");
|
b.HasIndex("SystemId");
|
||||||
|
|
||||||
b.ToTable("tech_message");
|
b.ToTable("TechMessage");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TimestampedValues", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.TimestampedSet", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("DiscriminatorId")
|
b.Property<Guid>("IdDiscriminator")
|
||||||
.HasColumnType("uuid")
|
.HasColumnType("uuid")
|
||||||
.HasComment("Дискриминатор системы");
|
.HasComment("Дискриминатор ссылка на тип сохраняемых данных");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("Timestamp")
|
b.Property<DateTimeOffset>("Timestamp")
|
||||||
.HasColumnType("timestamp with time zone")
|
.HasColumnType("timestamp with time zone")
|
||||||
.HasComment("Временная отметка");
|
.HasComment("Отметка времени, строго в UTC");
|
||||||
|
|
||||||
b.Property<string>("Values")
|
b.Property<string>("Set")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasComment("Данные");
|
.HasComment("Набор сохраняемых данных");
|
||||||
|
|
||||||
b.HasKey("DiscriminatorId", "Timestamp");
|
b.HasKey("IdDiscriminator", "Timestamp");
|
||||||
|
|
||||||
b.ToTable("timestamped_values");
|
b.ToTable("TimestampedSets", t =>
|
||||||
|
{
|
||||||
|
t.HasComment("Общая таблица данных временных рядов");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Model.ChangeLog", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Model.ChangeLog", b =>
|
||||||
@ -193,7 +178,90 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("change_log");
|
b.ToTable("ChangeLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DD.Persistence.Database.Model.DataSaub", b =>
|
||||||
|
{
|
||||||
|
b.Property<DateTimeOffset>("Date")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("date");
|
||||||
|
|
||||||
|
b.Property<double?>("AxialLoad")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("axialLoad");
|
||||||
|
|
||||||
|
b.Property<double?>("BitDepth")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("bitDepth");
|
||||||
|
|
||||||
|
b.Property<double?>("BlockPosition")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("blockPosition");
|
||||||
|
|
||||||
|
b.Property<double?>("BlockSpeed")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("blockSpeed");
|
||||||
|
|
||||||
|
b.Property<double?>("Flow")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("flow");
|
||||||
|
|
||||||
|
b.Property<double?>("HookWeight")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("hookWeight");
|
||||||
|
|
||||||
|
b.Property<int>("IdFeedRegulator")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("idFeedRegulator");
|
||||||
|
|
||||||
|
b.Property<int?>("Mode")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("mode");
|
||||||
|
|
||||||
|
b.Property<double?>("Mse")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("mse");
|
||||||
|
|
||||||
|
b.Property<short>("MseState")
|
||||||
|
.HasColumnType("smallint")
|
||||||
|
.HasColumnName("mseState");
|
||||||
|
|
||||||
|
b.Property<double?>("Pressure")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("pressure");
|
||||||
|
|
||||||
|
b.Property<double?>("Pump0Flow")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("pump0Flow");
|
||||||
|
|
||||||
|
b.Property<double?>("Pump1Flow")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("pump1Flow");
|
||||||
|
|
||||||
|
b.Property<double?>("Pump2Flow")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("pump2Flow");
|
||||||
|
|
||||||
|
b.Property<double?>("RotorSpeed")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("rotorSpeed");
|
||||||
|
|
||||||
|
b.Property<double?>("RotorTorque")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("rotorTorque");
|
||||||
|
|
||||||
|
b.Property<string>("User")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("user");
|
||||||
|
|
||||||
|
b.Property<double?>("WellDepth")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("wellDepth");
|
||||||
|
|
||||||
|
b.HasKey("Date");
|
||||||
|
|
||||||
|
b.ToTable("DataSaub");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Model.Setpoint", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Model.Setpoint", b =>
|
||||||
@ -202,7 +270,7 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
.HasColumnType("uuid")
|
.HasColumnType("uuid")
|
||||||
.HasComment("Ключ");
|
.HasComment("Ключ");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("Timestamp")
|
b.Property<DateTimeOffset>("Created")
|
||||||
.HasColumnType("timestamp with time zone")
|
.HasColumnType("timestamp with time zone")
|
||||||
.HasComment("Дата создания уставки");
|
.HasComment("Дата создания уставки");
|
||||||
|
|
||||||
@ -210,13 +278,14 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
.HasColumnType("uuid")
|
.HasColumnType("uuid")
|
||||||
.HasComment("Id автора последнего изменения");
|
.HasComment("Id автора последнего изменения");
|
||||||
|
|
||||||
b.Property<JsonElement>("Value")
|
b.Property<object>("Value")
|
||||||
|
.IsRequired()
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasComment("Значение уставки");
|
.HasComment("Значение уставки");
|
||||||
|
|
||||||
b.HasKey("Key", "Timestamp");
|
b.HasKey("Key", "Created");
|
||||||
|
|
||||||
b.ToTable("setpoint");
|
b.ToTable("Setpoint");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b =>
|
||||||
@ -229,17 +298,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.Navigation("System");
|
b.Navigation("System");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TimestampedValues", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("DD.Persistence.Database.Entity.DataScheme", "DataScheme")
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("DiscriminatorId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("DataScheme");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Text.Json;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
@ -13,7 +12,7 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "change_log",
|
name: "ChangeLog",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false, comment: "Ключ записи"),
|
Id = table.Column<Guid>(type: "uuid", nullable: false, comment: "Ключ записи"),
|
||||||
@ -30,23 +29,40 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_change_log", x => x.Id);
|
table.PrimaryKey("PK_ChangeLog", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "data_scheme",
|
name: "DataSaub",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
DiscriminatorId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Идентификатор схемы данных"),
|
date = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||||
PropNames = table.Column<string>(type: "jsonb", nullable: false, comment: "Наименования полей в порядке индексации")
|
mode = table.Column<int>(type: "integer", nullable: true),
|
||||||
|
user = table.Column<string>(type: "text", nullable: true),
|
||||||
|
wellDepth = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
bitDepth = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
blockPosition = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
blockSpeed = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
pressure = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
axialLoad = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
hookWeight = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
rotorTorque = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
rotorSpeed = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
flow = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
mseState = table.Column<short>(type: "smallint", nullable: false),
|
||||||
|
idFeedRegulator = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
mse = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
pump0Flow = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
pump1Flow = table.Column<double>(type: "double precision", nullable: true),
|
||||||
|
pump2Flow = table.Column<double>(type: "double precision", nullable: true)
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_data_scheme", x => x.DiscriminatorId);
|
table.PrimaryKey("PK_DataSaub", x => x.date);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "data_source_system",
|
name: "DataSourceSystem",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
SystemId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Id системы - источника данных"),
|
SystemId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Id системы - источника данных"),
|
||||||
@ -55,11 +71,11 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_data_source_system", x => x.SystemId);
|
table.PrimaryKey("PK_DataSourceSystem", x => x.SystemId);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "parameter_data",
|
name: "ParameterData",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
DiscriminatorId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Дискриминатор системы"),
|
DiscriminatorId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Дискриминатор системы"),
|
||||||
@ -69,44 +85,39 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_parameter_data", x => new { x.DiscriminatorId, x.ParameterId, x.Timestamp });
|
table.PrimaryKey("PK_ParameterData", x => new { x.DiscriminatorId, x.ParameterId, x.Timestamp });
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "setpoint",
|
name: "Setpoint",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Key = table.Column<Guid>(type: "uuid", nullable: false, comment: "Ключ"),
|
Key = table.Column<Guid>(type: "uuid", nullable: false, comment: "Ключ"),
|
||||||
Timestamp = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Дата создания уставки"),
|
Created = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Дата создания уставки"),
|
||||||
Value = table.Column<JsonElement>(type: "jsonb", nullable: false, comment: "Значение уставки"),
|
Value = table.Column<object>(type: "jsonb", nullable: false, comment: "Значение уставки"),
|
||||||
IdUser = table.Column<Guid>(type: "uuid", nullable: false, comment: "Id автора последнего изменения")
|
IdUser = table.Column<Guid>(type: "uuid", nullable: false, comment: "Id автора последнего изменения")
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_setpoint", x => new { x.Key, x.Timestamp });
|
table.PrimaryKey("PK_Setpoint", x => new { x.Key, x.Created });
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "timestamped_values",
|
name: "TimestampedSets",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Timestamp = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Временная отметка"),
|
IdDiscriminator = table.Column<Guid>(type: "uuid", nullable: false, comment: "Дискриминатор ссылка на тип сохраняемых данных"),
|
||||||
DiscriminatorId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Дискриминатор системы"),
|
Timestamp = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Отметка времени, строго в UTC"),
|
||||||
Values = table.Column<string>(type: "jsonb", nullable: false, comment: "Данные")
|
Set = table.Column<string>(type: "jsonb", nullable: false, comment: "Набор сохраняемых данных")
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_timestamped_values", x => new { x.DiscriminatorId, x.Timestamp });
|
table.PrimaryKey("PK_TimestampedSets", x => new { x.IdDiscriminator, x.Timestamp });
|
||||||
table.ForeignKey(
|
},
|
||||||
name: "FK_timestamped_values_data_scheme_DiscriminatorId",
|
comment: "Общая таблица данных временных рядов");
|
||||||
column: x => x.DiscriminatorId,
|
|
||||||
principalTable: "data_scheme",
|
|
||||||
principalColumn: "DiscriminatorId",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "tech_message",
|
name: "TechMessage",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
EventId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Id события"),
|
EventId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Id события"),
|
||||||
@ -118,18 +129,18 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_tech_message", x => x.EventId);
|
table.PrimaryKey("PK_TechMessage", x => x.EventId);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_tech_message_data_source_system_SystemId",
|
name: "FK_TechMessage_DataSourceSystem_SystemId",
|
||||||
column: x => x.SystemId,
|
column: x => x.SystemId,
|
||||||
principalTable: "data_source_system",
|
principalTable: "DataSourceSystem",
|
||||||
principalColumn: "SystemId",
|
principalColumn: "SystemId",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_tech_message_SystemId",
|
name: "IX_TechMessage_SystemId",
|
||||||
table: "tech_message",
|
table: "TechMessage",
|
||||||
column: "SystemId");
|
column: "SystemId");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,25 +148,25 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "change_log");
|
name: "ChangeLog");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "parameter_data");
|
name: "DataSaub");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "setpoint");
|
name: "ParameterData");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "tech_message");
|
name: "Setpoint");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "timestamped_values");
|
name: "TechMessage");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "data_source_system");
|
name: "TimestampedSets");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "data_scheme");
|
name: "DataSourceSystem");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,5 @@
|
|||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using System;
|
using System;
|
||||||
using System.Text.Json;
|
|
||||||
using DD.Persistence.Database.Model;
|
using DD.Persistence.Database.Model;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
@ -18,28 +17,11 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "9.0.0")
|
.HasAnnotation("ProductVersion", "8.0.10")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataScheme", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("DiscriminatorId")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid")
|
|
||||||
.HasComment("Идентификатор схемы данных");
|
|
||||||
|
|
||||||
b.Property<string>("PropNames")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("jsonb")
|
|
||||||
.HasComment("Наименования полей в порядке индексации");
|
|
||||||
|
|
||||||
b.HasKey("DiscriminatorId");
|
|
||||||
|
|
||||||
b.ToTable("data_scheme");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("SystemId")
|
b.Property<Guid>("SystemId")
|
||||||
@ -58,7 +40,7 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.HasKey("SystemId");
|
b.HasKey("SystemId");
|
||||||
|
|
||||||
b.ToTable("data_source_system");
|
b.ToTable("DataSourceSystem");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.ParameterData", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.ParameterData", b =>
|
||||||
@ -82,7 +64,7 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.HasKey("DiscriminatorId", "ParameterId", "Timestamp");
|
b.HasKey("DiscriminatorId", "ParameterId", "Timestamp");
|
||||||
|
|
||||||
b.ToTable("parameter_data");
|
b.ToTable("ParameterData");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b =>
|
||||||
@ -117,27 +99,30 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.HasIndex("SystemId");
|
b.HasIndex("SystemId");
|
||||||
|
|
||||||
b.ToTable("tech_message");
|
b.ToTable("TechMessage");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TimestampedValues", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.TimestampedSet", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("DiscriminatorId")
|
b.Property<Guid>("IdDiscriminator")
|
||||||
.HasColumnType("uuid")
|
.HasColumnType("uuid")
|
||||||
.HasComment("Дискриминатор системы");
|
.HasComment("Дискриминатор ссылка на тип сохраняемых данных");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("Timestamp")
|
b.Property<DateTimeOffset>("Timestamp")
|
||||||
.HasColumnType("timestamp with time zone")
|
.HasColumnType("timestamp with time zone")
|
||||||
.HasComment("Временная отметка");
|
.HasComment("Отметка времени, строго в UTC");
|
||||||
|
|
||||||
b.Property<string>("Values")
|
b.Property<string>("Set")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasComment("Данные");
|
.HasComment("Набор сохраняемых данных");
|
||||||
|
|
||||||
b.HasKey("DiscriminatorId", "Timestamp");
|
b.HasKey("IdDiscriminator", "Timestamp");
|
||||||
|
|
||||||
b.ToTable("timestamped_values");
|
b.ToTable("TimestampedSets", t =>
|
||||||
|
{
|
||||||
|
t.HasComment("Общая таблица данных временных рядов");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Model.ChangeLog", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Model.ChangeLog", b =>
|
||||||
@ -190,7 +175,90 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("change_log");
|
b.ToTable("ChangeLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DD.Persistence.Database.Model.DataSaub", b =>
|
||||||
|
{
|
||||||
|
b.Property<DateTimeOffset>("Date")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("date");
|
||||||
|
|
||||||
|
b.Property<double?>("AxialLoad")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("axialLoad");
|
||||||
|
|
||||||
|
b.Property<double?>("BitDepth")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("bitDepth");
|
||||||
|
|
||||||
|
b.Property<double?>("BlockPosition")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("blockPosition");
|
||||||
|
|
||||||
|
b.Property<double?>("BlockSpeed")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("blockSpeed");
|
||||||
|
|
||||||
|
b.Property<double?>("Flow")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("flow");
|
||||||
|
|
||||||
|
b.Property<double?>("HookWeight")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("hookWeight");
|
||||||
|
|
||||||
|
b.Property<int>("IdFeedRegulator")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("idFeedRegulator");
|
||||||
|
|
||||||
|
b.Property<int?>("Mode")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("mode");
|
||||||
|
|
||||||
|
b.Property<double?>("Mse")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("mse");
|
||||||
|
|
||||||
|
b.Property<short>("MseState")
|
||||||
|
.HasColumnType("smallint")
|
||||||
|
.HasColumnName("mseState");
|
||||||
|
|
||||||
|
b.Property<double?>("Pressure")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("pressure");
|
||||||
|
|
||||||
|
b.Property<double?>("Pump0Flow")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("pump0Flow");
|
||||||
|
|
||||||
|
b.Property<double?>("Pump1Flow")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("pump1Flow");
|
||||||
|
|
||||||
|
b.Property<double?>("Pump2Flow")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("pump2Flow");
|
||||||
|
|
||||||
|
b.Property<double?>("RotorSpeed")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("rotorSpeed");
|
||||||
|
|
||||||
|
b.Property<double?>("RotorTorque")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("rotorTorque");
|
||||||
|
|
||||||
|
b.Property<string>("User")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("user");
|
||||||
|
|
||||||
|
b.Property<double?>("WellDepth")
|
||||||
|
.HasColumnType("double precision")
|
||||||
|
.HasColumnName("wellDepth");
|
||||||
|
|
||||||
|
b.HasKey("Date");
|
||||||
|
|
||||||
|
b.ToTable("DataSaub");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Model.Setpoint", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Model.Setpoint", b =>
|
||||||
@ -199,7 +267,7 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
.HasColumnType("uuid")
|
.HasColumnType("uuid")
|
||||||
.HasComment("Ключ");
|
.HasComment("Ключ");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("Timestamp")
|
b.Property<DateTimeOffset>("Created")
|
||||||
.HasColumnType("timestamp with time zone")
|
.HasColumnType("timestamp with time zone")
|
||||||
.HasComment("Дата создания уставки");
|
.HasComment("Дата создания уставки");
|
||||||
|
|
||||||
@ -207,13 +275,14 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
.HasColumnType("uuid")
|
.HasColumnType("uuid")
|
||||||
.HasComment("Id автора последнего изменения");
|
.HasComment("Id автора последнего изменения");
|
||||||
|
|
||||||
b.Property<JsonElement>("Value")
|
b.Property<object>("Value")
|
||||||
|
.IsRequired()
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasComment("Значение уставки");
|
.HasComment("Значение уставки");
|
||||||
|
|
||||||
b.HasKey("Key", "Timestamp");
|
b.HasKey("Key", "Created");
|
||||||
|
|
||||||
b.ToTable("setpoint");
|
b.ToTable("Setpoint");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b =>
|
||||||
@ -226,17 +295,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.Navigation("System");
|
b.Navigation("System");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TimestampedValues", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("DD.Persistence.Database.Entity.DataScheme", "DataScheme")
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("DiscriminatorId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("DataScheme");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
|
|
||||||
using DD.Persistence.Database.EntityAbstractions;
|
|
||||||
using DD.Persistence.ModelsAbstractions;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using DD.Persistence.Models;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Entity;
|
namespace DD.Persistence.Database.Model;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Часть записи, описывающая изменение
|
/// Часть записи, описывающая изменение
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Table("change_log")]
|
public class ChangeLog : IChangeLog, IWithSectionPart
|
||||||
public class ChangeLog : IChangeLog
|
|
||||||
{
|
{
|
||||||
[Key, Comment("Ключ записи")]
|
[Key, Comment("Ключ записи")]
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
@ -34,6 +32,15 @@ public class ChangeLog : IChangeLog
|
|||||||
[Comment("Id заменяющей записи")]
|
[Comment("Id заменяющей записи")]
|
||||||
public Guid? IdNext { get; set; }
|
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("Значение")]
|
[Column(TypeName = "jsonb"), Comment("Значение")]
|
||||||
public required IDictionary<string, object> Value { get; set; }
|
public required IDictionary<string, object> Value { get; set; }
|
||||||
}
|
}
|
||||||
|
63
DD.Persistence.Database/Entity/DataSaub.cs
Normal file
63
DD.Persistence.Database/Entity/DataSaub.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Database.Model;
|
||||||
|
public class DataSaub : ITimestampedData
|
||||||
|
{
|
||||||
|
[Key, Column("date")]
|
||||||
|
public DateTimeOffset Date { get; set; }
|
||||||
|
|
||||||
|
[Column("mode")]
|
||||||
|
public int? Mode { get; set; }
|
||||||
|
|
||||||
|
[Column("user")]
|
||||||
|
public string? User { get; set; }
|
||||||
|
|
||||||
|
[Column("wellDepth")]
|
||||||
|
public double? WellDepth { get; set; }
|
||||||
|
|
||||||
|
[Column("bitDepth")]
|
||||||
|
public double? BitDepth { get; set; }
|
||||||
|
|
||||||
|
[Column("blockPosition")]
|
||||||
|
public double? BlockPosition { get; set; }
|
||||||
|
|
||||||
|
[Column("blockSpeed")]
|
||||||
|
public double? BlockSpeed { get; set; }
|
||||||
|
|
||||||
|
[Column("pressure")]
|
||||||
|
public double? Pressure { get; set; }
|
||||||
|
|
||||||
|
[Column("axialLoad")]
|
||||||
|
public double? AxialLoad { get; set; }
|
||||||
|
|
||||||
|
[Column("hookWeight")]
|
||||||
|
public double? HookWeight { get; set; }
|
||||||
|
|
||||||
|
[Column("rotorTorque")]
|
||||||
|
public double? RotorTorque { get; set; }
|
||||||
|
|
||||||
|
[Column("rotorSpeed")]
|
||||||
|
public double? RotorSpeed { get; set; }
|
||||||
|
|
||||||
|
[Column("flow")]
|
||||||
|
public double? Flow { get; set; }
|
||||||
|
|
||||||
|
[Column("mseState")]
|
||||||
|
public short MseState { get; set; }
|
||||||
|
|
||||||
|
[Column("idFeedRegulator")]
|
||||||
|
public int IdFeedRegulator { get; set; }
|
||||||
|
|
||||||
|
[Column("mse")]
|
||||||
|
public double? Mse { get; set; }
|
||||||
|
|
||||||
|
[Column("pump0Flow")]
|
||||||
|
public double? Pump0Flow { get; set; }
|
||||||
|
|
||||||
|
[Column("pump1Flow")]
|
||||||
|
public double? Pump1Flow { get; set; }
|
||||||
|
|
||||||
|
[Column("pump2Flow")]
|
||||||
|
public double? Pump2Flow { get; set; }
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Entity;
|
|
||||||
|
|
||||||
[Table("data_scheme")]
|
|
||||||
public class DataScheme
|
|
||||||
{
|
|
||||||
[Key, Comment("Идентификатор схемы данных"),]
|
|
||||||
public Guid DiscriminatorId { get; set; }
|
|
||||||
|
|
||||||
[Comment("Наименования полей в порядке индексации"), Column(TypeName = "jsonb")]
|
|
||||||
public string[] PropNames { get; set; } = [];
|
|
||||||
}
|
|
@ -3,15 +3,13 @@ using System.ComponentModel.DataAnnotations;
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Entity;
|
namespace DD.Persistence.Database.Entity;
|
||||||
|
|
||||||
[Table("data_source_system")]
|
|
||||||
public class DataSourceSystem
|
public class DataSourceSystem
|
||||||
{
|
{
|
||||||
[Key, Comment("Id системы - источника данных")]
|
[Key, Comment("Id системы - источника данных")]
|
||||||
public Guid SystemId { get; set; }
|
public Guid SystemId { get; set; }
|
||||||
|
|
||||||
[Required, Column(TypeName = "varchar(256)"), Comment("Наименование системы - источника данных")]
|
[Required, Column(TypeName = "varchar(256)"), Comment("Наименование системы - источника данных")]
|
||||||
public string Name { get; set; } = string.Empty;
|
public required string Name { get; set; }
|
||||||
|
|
||||||
[Comment("Описание системы - источника данных")]
|
[Comment("Описание системы - источника данных")]
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
namespace DD.Persistence.Database.EntityAbstractions;
|
|
||||||
|
namespace DD.Persistence.Database.Model;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Часть записи, описывающая изменение
|
/// Часть записи, описывающая изменение
|
8
DD.Persistence.Database/Entity/ITimestampedData.cs
Normal file
8
DD.Persistence.Database/Entity/ITimestampedData.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace DD.Persistence.Database.Model;
|
||||||
|
public interface ITimestampedData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Дата (должна быть обязательно в UTC)
|
||||||
|
/// </summary>
|
||||||
|
DateTimeOffset Date { get; set; }
|
||||||
|
}
|
@ -1,13 +1,11 @@
|
|||||||
using DD.Persistence.Database.EntityAbstractions;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Entity;
|
namespace DD.Persistence.Database.Entity;
|
||||||
|
|
||||||
[Table("parameter_data")]
|
|
||||||
[PrimaryKey(nameof(DiscriminatorId), nameof(ParameterId), nameof(Timestamp))]
|
[PrimaryKey(nameof(DiscriminatorId), nameof(ParameterId), nameof(Timestamp))]
|
||||||
public class ParameterData : ITimestampedItem
|
public class ParameterData
|
||||||
{
|
{
|
||||||
[Required, Comment("Дискриминатор системы")]
|
[Required, Comment("Дискриминатор системы")]
|
||||||
public Guid DiscriminatorId { get; set; }
|
public Guid DiscriminatorId { get; set; }
|
||||||
|
@ -1,23 +1,22 @@
|
|||||||
using DD.Persistence.Database.EntityAbstractions;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Entity;
|
namespace DD.Persistence.Database.Model
|
||||||
|
|
||||||
[Table("setpoint")]
|
|
||||||
[PrimaryKey(nameof(Key), nameof(Timestamp))]
|
|
||||||
public class Setpoint : ITimestampedItem
|
|
||||||
{
|
{
|
||||||
[Comment("Ключ")]
|
[PrimaryKey(nameof(Key), nameof(Created))]
|
||||||
public Guid Key { get; set; }
|
public class Setpoint
|
||||||
|
{
|
||||||
|
[Comment("Ключ")]
|
||||||
|
public Guid Key { get; set; }
|
||||||
|
|
||||||
[Column(TypeName = "jsonb"), Comment("Значение уставки")]
|
[Column(TypeName = "jsonb"), Comment("Значение уставки")]
|
||||||
public required JsonElement Value { get; set; }
|
public required JsonElement Value { get; set; }
|
||||||
|
|
||||||
[Comment("Дата создания уставки")]
|
[Comment("Дата создания уставки")]
|
||||||
public DateTimeOffset Timestamp { get; set; }
|
public DateTimeOffset Created { get; set; }
|
||||||
|
|
||||||
[Comment("Id автора последнего изменения")]
|
[Comment("Id автора последнего изменения")]
|
||||||
public Guid IdUser { get; set; }
|
public Guid IdUser { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
using DD.Persistence.Database.EntityAbstractions;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Entity;
|
namespace DD.Persistence.Database.Entity
|
||||||
|
|
||||||
[Table("tech_message")]
|
|
||||||
public class TechMessage : ITimestampedItem
|
|
||||||
{
|
{
|
||||||
[Key, Comment("Id события")]
|
public class TechMessage
|
||||||
public Guid EventId { get; set; }
|
{
|
||||||
|
[Key, Comment("Id события")]
|
||||||
|
public Guid EventId { get; set; }
|
||||||
|
|
||||||
[Comment("Id Категории важности")]
|
[Comment("Id Категории важности")]
|
||||||
public int CategoryId { get; set; }
|
public int CategoryId { get; set; }
|
||||||
|
|
||||||
[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; }
|
||||||
@ -29,3 +27,4 @@ public class TechMessage : ITimestampedItem
|
|||||||
[Comment("Статус события")]
|
[Comment("Статус события")]
|
||||||
public int EventState { get; set; }
|
public int EventState { get; set; }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
11
DD.Persistence.Database/Entity/TimestampedSet.cs
Normal file
11
DD.Persistence.Database/Entity/TimestampedSet.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Database.Entity;
|
||||||
|
|
||||||
|
[Comment("Общая таблица данных временных рядов")]
|
||||||
|
[PrimaryKey(nameof(IdDiscriminator), nameof(Timestamp))]
|
||||||
|
public record TimestampedSet(
|
||||||
|
[property: Comment("Дискриминатор ссылка на тип сохраняемых данных")] Guid IdDiscriminator,
|
||||||
|
[property: Comment("Отметка времени, строго в UTC")] DateTimeOffset Timestamp,
|
||||||
|
[property: Column(TypeName = "jsonb"), Comment("Набор сохраняемых данных")] IDictionary<string, object> Set);
|
@ -1,23 +0,0 @@
|
|||||||
using DD.Persistence.Database.EntityAbstractions;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Entity;
|
|
||||||
|
|
||||||
[Table("timestamped_values")]
|
|
||||||
[PrimaryKey(nameof(DiscriminatorId), nameof(Timestamp))]
|
|
||||||
public class TimestampedValues : ITimestampedItem
|
|
||||||
{
|
|
||||||
[Comment("Временная отметка"), Key]
|
|
||||||
public DateTimeOffset Timestamp { get; set; }
|
|
||||||
|
|
||||||
[Comment("Дискриминатор системы"),]
|
|
||||||
public Guid DiscriminatorId { get; set; }
|
|
||||||
|
|
||||||
[Comment("Данные"), Column(TypeName = "jsonb")]
|
|
||||||
public required object[] Values { get; set; }
|
|
||||||
|
|
||||||
[Required, ForeignKey(nameof(DiscriminatorId)), Comment("Идентификаторы")]
|
|
||||||
public virtual DataScheme? DataScheme { get; set; }
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
namespace DD.Persistence.Database.EntityAbstractions;
|
|
||||||
public interface ITimestampedItem
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Дата (должна быть обязательно в UTC)
|
|
||||||
/// </summary>
|
|
||||||
DateTimeOffset Timestamp { get; set; }
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
using DD.Persistence.Database.Entity;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using DD.Persistence.Database.Entity;
|
||||||
|
using DD.Persistence.Database.Model;
|
||||||
|
|
||||||
namespace DD.Persistence.Database;
|
namespace DD.Persistence.Database;
|
||||||
|
|
||||||
@ -8,11 +9,11 @@ namespace DD.Persistence.Database;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PersistenceDbContext : DbContext
|
public class PersistenceDbContext : DbContext
|
||||||
{
|
{
|
||||||
|
public DbSet<DataSaub> DataSaub => Set<DataSaub>();
|
||||||
|
|
||||||
public DbSet<Setpoint> Setpoint => Set<Setpoint>();
|
public DbSet<Setpoint> Setpoint => Set<Setpoint>();
|
||||||
|
|
||||||
public DbSet<DataScheme> DataSchemes => Set<DataScheme>();
|
public DbSet<TimestampedSet> TimestampedSets => Set<TimestampedSet>();
|
||||||
|
|
||||||
public DbSet<TimestampedValues> TimestampedValues => Set<TimestampedValues>();
|
|
||||||
|
|
||||||
public DbSet<ChangeLog> ChangeLog => Set<ChangeLog>();
|
public DbSet<ChangeLog> ChangeLog => Set<ChangeLog>();
|
||||||
|
|
||||||
@ -30,12 +31,8 @@ public class PersistenceDbContext : DbContext
|
|||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
modelBuilder.Entity<DataScheme>()
|
modelBuilder.Entity<TimestampedSet>()
|
||||||
.Property(e => e.PropNames)
|
.Property(e => e.Set)
|
||||||
.HasJsonConversion();
|
|
||||||
|
|
||||||
modelBuilder.Entity<TimestampedValues>()
|
|
||||||
.Property(e => e.Values)
|
|
||||||
.HasJsonConversion();
|
.HasJsonConversion();
|
||||||
|
|
||||||
modelBuilder.Entity<ChangeLog>()
|
modelBuilder.Entity<ChangeLog>()
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
using DD.Persistence.Client;
|
|
||||||
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.Models;
|
|
||||||
using DD.Persistence.Models.Requests;
|
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using DD.Persistence.Database.Model;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using DD.Persistence.Models.Requests;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
using DD.Persistence.Client;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
|
using DD.Persistence.Client.Clients;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Refit;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace DD.Persistence.IntegrationTests.Controllers;
|
namespace DD.Persistence.IntegrationTests.Controllers;
|
||||||
public class ChangeLogControllerTest : BaseIntegrationTest
|
public class ChangeLogControllerTest : BaseIntegrationTest
|
||||||
@ -50,7 +52,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
|
|||||||
var insertedCount = 10;
|
var insertedCount = 10;
|
||||||
var createdResult = CreateChangeLogItems(insertedCount, (-15, 15));
|
var createdResult = CreateChangeLogItems(insertedCount, (-15, 15));
|
||||||
var idDiscriminator = createdResult.Item1;
|
var idDiscriminator = createdResult.Item1;
|
||||||
var dtos = createdResult.Item2.Select(e => e.Adapt<ChangeLogValuesDto>());
|
var dtos = createdResult.Item2.Select(e => e.Adapt<DataWithWellDepthAndSectionDto>());
|
||||||
|
|
||||||
// act
|
// act
|
||||||
var result = await client.ClearAndAddRange(idDiscriminator, dtos, new CancellationToken());
|
var result = await client.ClearAndAddRange(idDiscriminator, dtos, new CancellationToken());
|
||||||
@ -104,7 +106,8 @@ public class ChangeLogControllerTest : BaseIntegrationTest
|
|||||||
var entity = dbContext.ChangeLog
|
var entity = dbContext.ChangeLog
|
||||||
.Where(x => x.IdDiscriminator == idDiscriminator)
|
.Where(x => x.IdDiscriminator == idDiscriminator)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
dto = entity.Adapt<ChangeLogValuesDto>();
|
dto = entity.Adapt<DataWithWellDepthAndSectionDto>();
|
||||||
|
dto.DepthEnd += 10;
|
||||||
|
|
||||||
// act
|
// act
|
||||||
result = await client.Update(dto, new CancellationToken());
|
result = await client.Update(dto, new CancellationToken());
|
||||||
@ -146,9 +149,12 @@ public class ChangeLogControllerTest : BaseIntegrationTest
|
|||||||
dbContext.ChangeLog.AddRange(entities);
|
dbContext.ChangeLog.AddRange(entities);
|
||||||
dbContext.SaveChanges();
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
dtos = entities.Select(c => new ChangeLogValuesDto()
|
dtos = entities.Select(c => new DataWithWellDepthAndSectionDto()
|
||||||
{
|
{
|
||||||
|
DepthEnd = c.DepthEnd + 10,
|
||||||
|
DepthStart = c.DepthStart + 10,
|
||||||
Id = c.Id,
|
Id = c.Id,
|
||||||
|
IdSection = c.IdSection,
|
||||||
Value = c.Value
|
Value = c.Value
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
@ -239,6 +245,12 @@ public class ChangeLogControllerTest : BaseIntegrationTest
|
|||||||
|
|
||||||
var deletedCount = await client.DeleteRange(idsToDelete, new CancellationToken());
|
var deletedCount = await client.DeleteRange(idsToDelete, new CancellationToken());
|
||||||
|
|
||||||
|
var filterRequest = new SectionPartRequest()
|
||||||
|
{
|
||||||
|
DepthStart = 0,
|
||||||
|
DepthEnd = 1000,
|
||||||
|
};
|
||||||
|
|
||||||
var paginationRequest = new PaginationRequest()
|
var paginationRequest = new PaginationRequest()
|
||||||
{
|
{
|
||||||
Skip = 0,
|
Skip = 0,
|
||||||
@ -247,7 +259,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
|
|||||||
};
|
};
|
||||||
|
|
||||||
var moment = DateTimeOffset.UtcNow.AddDays(16);
|
var moment = DateTimeOffset.UtcNow.AddDays(16);
|
||||||
var result = await client.GetByDate(idDiscriminator, moment, paginationRequest, new CancellationToken());
|
var result = await client.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, new CancellationToken());
|
||||||
|
|
||||||
Assert.NotNull(result);
|
Assert.NotNull(result);
|
||||||
|
|
||||||
@ -280,7 +292,11 @@ public class ChangeLogControllerTest : BaseIntegrationTest
|
|||||||
var idDiscriminator = changeLogItems.Item1;
|
var idDiscriminator = changeLogItems.Item1;
|
||||||
var entities = changeLogItems.Item2;
|
var entities = changeLogItems.Item2;
|
||||||
|
|
||||||
var dtos = entities.Select(e => e.Adapt<ChangeLogValuesDto>()).ToArray();
|
foreach (var entity in entities)
|
||||||
|
{
|
||||||
|
entity.DepthEnd += 10;
|
||||||
|
}
|
||||||
|
var dtos = entities.Select(e => e.Adapt<DataWithWellDepthAndSectionDto>()).ToArray();
|
||||||
await client.UpdateRange(dtos, new CancellationToken());
|
await client.UpdateRange(dtos, new CancellationToken());
|
||||||
|
|
||||||
//act
|
//act
|
||||||
@ -294,16 +310,19 @@ public class ChangeLogControllerTest : BaseIntegrationTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static IEnumerable<ChangeLogValuesDto> Generate(int count)
|
private static IEnumerable<DataWithWellDepthAndSectionDto> Generate(int count)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
yield return new ChangeLogValuesDto()
|
yield return new DataWithWellDepthAndSectionDto()
|
||||||
{
|
{
|
||||||
Value = new Dictionary<string, object>()
|
Value = new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ "Key", 1 }
|
{ "Key", 1 }
|
||||||
},
|
},
|
||||||
Id = Guid.NewGuid()
|
DepthStart = generatorRandomDigits.Next(1, 5),
|
||||||
|
DepthEnd = generatorRandomDigits.Next(5, 15),
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
IdSection = Guid.NewGuid()
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
using DD.Persistence.Database.Model;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace DD.Persistence.IntegrationTests.Controllers;
|
||||||
|
public class DataSaubControllerTest : TimeSeriesBaseControllerTest<DataSaub, DataSaubDto>
|
||||||
|
{
|
||||||
|
private readonly DataSaubDto dto = new()
|
||||||
|
{
|
||||||
|
AxialLoad = 1,
|
||||||
|
BitDepth = 2,
|
||||||
|
BlockPosition = 3,
|
||||||
|
BlockSpeed = 4,
|
||||||
|
Date = DateTimeOffset.UtcNow,
|
||||||
|
Flow = 5,
|
||||||
|
HookWeight = 6,
|
||||||
|
IdFeedRegulator = 8,
|
||||||
|
Mode = 9,
|
||||||
|
Mse = 10,
|
||||||
|
MseState = 11,
|
||||||
|
Pressure = 12,
|
||||||
|
Pump0Flow = 13,
|
||||||
|
Pump1Flow = 14,
|
||||||
|
Pump2Flow = 15,
|
||||||
|
RotorSpeed = 16,
|
||||||
|
RotorTorque = 17,
|
||||||
|
User = string.Empty,
|
||||||
|
WellDepth = 18,
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly DataSaub entity = new()
|
||||||
|
{
|
||||||
|
AxialLoad = 1,
|
||||||
|
BitDepth = 2,
|
||||||
|
BlockPosition = 3,
|
||||||
|
BlockSpeed = 4,
|
||||||
|
Date = DateTimeOffset.UtcNow,
|
||||||
|
Flow = 5,
|
||||||
|
HookWeight = 6,
|
||||||
|
IdFeedRegulator = 8,
|
||||||
|
Mode = 9,
|
||||||
|
Mse = 10,
|
||||||
|
MseState = 11,
|
||||||
|
Pressure = 12,
|
||||||
|
Pump0Flow = 13,
|
||||||
|
Pump1Flow = 14,
|
||||||
|
Pump2Flow = 15,
|
||||||
|
RotorSpeed = 16,
|
||||||
|
RotorTorque = 17,
|
||||||
|
User = string.Empty,
|
||||||
|
WellDepth = 18,
|
||||||
|
};
|
||||||
|
|
||||||
|
public DataSaubControllerTest(WebAppFactoryFixture factory) : base(factory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task InsertRange_returns_success()
|
||||||
|
{
|
||||||
|
await InsertRangeSuccess(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_returns_success()
|
||||||
|
{
|
||||||
|
var beginDate = DateTimeOffset.UtcNow.AddDays(-1);
|
||||||
|
var endDate = DateTimeOffset.UtcNow;
|
||||||
|
await GetSuccess(beginDate, endDate, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetDatesRange_returns_success()
|
||||||
|
{
|
||||||
|
await GetDatesRangeSuccess(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetResampledData_returns_success()
|
||||||
|
{
|
||||||
|
await GetResampledDataSuccess(entity);
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
using DD.Persistence.Client;
|
|
||||||
using DD.Persistence.Client.Clients;
|
|
||||||
using DD.Persistence.Client.Clients.Interfaces;
|
|
||||||
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
|
||||||
using DD.Persistence.Database.Entity;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using DD.Persistence.Client;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
using DD.Persistence.Database.Model;
|
||||||
|
using System.Net;
|
||||||
|
using Xunit;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
|
using DD.Persistence.Client.Clients;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace DD.Persistence.IntegrationTests.Controllers
|
namespace DD.Persistence.IntegrationTests.Controllers
|
||||||
{
|
{
|
||||||
@ -14,6 +15,12 @@ namespace DD.Persistence.IntegrationTests.Controllers
|
|||||||
{
|
{
|
||||||
private readonly ISetpointClient setpointClient;
|
private readonly ISetpointClient setpointClient;
|
||||||
private readonly SetpointConfigStorage configStorage;
|
private readonly SetpointConfigStorage configStorage;
|
||||||
|
|
||||||
|
private class TestObject
|
||||||
|
{
|
||||||
|
public string? Value1 { get; set; }
|
||||||
|
public int? Value2 { get; set; }
|
||||||
|
}
|
||||||
public SetpointControllerTest(WebAppFactoryFixture factory) : base(factory)
|
public SetpointControllerTest(WebAppFactoryFixture factory) : base(factory)
|
||||||
{
|
{
|
||||||
var refitClientFactory = scope.ServiceProvider
|
var refitClientFactory = scope.ServiceProvider
|
||||||
@ -177,7 +184,7 @@ namespace DD.Persistence.IntegrationTests.Controllers
|
|||||||
|
|
||||||
await Add();
|
await Add();
|
||||||
|
|
||||||
var dateBegin = DateTimeOffset.UtcNow.AddDays(-1);
|
var dateBegin = DateTimeOffset.MinValue;
|
||||||
var take = 1;
|
var take = 1;
|
||||||
var part = await setpointClient.GetPart(dateBegin, take, CancellationToken.None);
|
var part = await setpointClient.GetPart(dateBegin, take, CancellationToken.None);
|
||||||
|
|
||||||
@ -188,17 +195,14 @@ namespace DD.Persistence.IntegrationTests.Controllers
|
|||||||
Assert.NotNull(response);
|
Assert.NotNull(response);
|
||||||
|
|
||||||
var expectedValue = part!
|
var expectedValue = part!
|
||||||
.FirstOrDefault()!.Timestamp
|
.FirstOrDefault()!.Created
|
||||||
.ToUniversalTime()
|
.ToString("dd.MM.yyyy-HH:mm:ss");
|
||||||
.ToString();
|
|
||||||
var actualValueFrom = response.From
|
var actualValueFrom = response.From
|
||||||
.ToUniversalTime()
|
.ToString("dd.MM.yyyy-HH:mm:ss");
|
||||||
.ToString();
|
|
||||||
Assert.Equal(expectedValue, actualValueFrom);
|
Assert.Equal(expectedValue, actualValueFrom);
|
||||||
|
|
||||||
var actualValueTo = response.To
|
var actualValueTo = response.To
|
||||||
.ToUniversalTime()
|
.ToString("dd.MM.yyyy-HH:mm:ss");
|
||||||
.ToString();
|
|
||||||
Assert.Equal(expectedValue, actualValueTo);
|
Assert.Equal(expectedValue, actualValueTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +247,7 @@ namespace DD.Persistence.IntegrationTests.Controllers
|
|||||||
{
|
{
|
||||||
//arrange
|
//arrange
|
||||||
var setpointKey = Guid.NewGuid();
|
var setpointKey = Guid.NewGuid();
|
||||||
var setpointValue = new
|
var setpointValue = new TestObject()
|
||||||
{
|
{
|
||||||
Value1 = "1",
|
Value1 = "1",
|
||||||
Value2 = 2
|
Value2 = 2
|
||||||
|
@ -15,7 +15,7 @@ namespace DD.Persistence.IntegrationTests.Controllers
|
|||||||
{
|
{
|
||||||
public class TechMessagesControllerTest : BaseIntegrationTest
|
public class TechMessagesControllerTest : BaseIntegrationTest
|
||||||
{
|
{
|
||||||
private static readonly string SystemCacheKey = $"{typeof(DataSourceSystem).FullName}CacheKey";
|
private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DataSourceSystem).FullName}CacheKey";
|
||||||
private readonly ITechMessagesClient techMessagesClient;
|
private readonly ITechMessagesClient techMessagesClient;
|
||||||
private readonly IMemoryCache memoryCache;
|
private readonly IMemoryCache memoryCache;
|
||||||
public TechMessagesControllerTest(WebAppFactoryFixture factory) : base(factory)
|
public TechMessagesControllerTest(WebAppFactoryFixture factory) : base(factory)
|
||||||
|
@ -0,0 +1,122 @@
|
|||||||
|
using DD.Persistence.Client;
|
||||||
|
using DD.Persistence.Client.Clients;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
|
using DD.Persistence.Database.Model;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using Mapster;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace DD.Persistence.IntegrationTests.Controllers;
|
||||||
|
|
||||||
|
public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrationTest
|
||||||
|
where TEntity : class, ITimestampedData, new()
|
||||||
|
where TDto : class, ITimeSeriesAbstractDto, new()
|
||||||
|
{
|
||||||
|
private readonly ITimeSeriesClient<TDto> timeSeriesClient;
|
||||||
|
|
||||||
|
public TimeSeriesBaseControllerTest(WebAppFactoryFixture factory) : base(factory)
|
||||||
|
{
|
||||||
|
dbContext.CleanupDbSet<TEntity>();
|
||||||
|
|
||||||
|
var refitClientFactory = scope.ServiceProvider
|
||||||
|
.GetRequiredService<IRefitClientFactory<IRefitTimeSeriesClient<TDto>>>();
|
||||||
|
var logger = scope.ServiceProvider.GetRequiredService<ILogger<TimeSeriesClient<TDto>>>();
|
||||||
|
|
||||||
|
timeSeriesClient = scope.ServiceProvider
|
||||||
|
.GetRequiredService<ITimeSeriesClient<TDto>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InsertRangeSuccess(TDto dto)
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
var expected = dto.Adapt<TDto>();
|
||||||
|
|
||||||
|
//act
|
||||||
|
var response = await timeSeriesClient.AddRange(new TDto[] { expected }, new CancellationToken());
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(1, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task GetSuccess(DateTimeOffset beginDate, DateTimeOffset endDate, TEntity entity)
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
var dbset = dbContext.Set<TEntity>();
|
||||||
|
|
||||||
|
dbset.Add(entity);
|
||||||
|
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var response = await timeSeriesClient.Get(beginDate, endDate, new CancellationToken());
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.NotNull(response);
|
||||||
|
Assert.Single(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task GetDatesRangeSuccess(TEntity entity)
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
var datesRangeExpected = 30;
|
||||||
|
|
||||||
|
var entity2 = entity.Adapt<TEntity>();
|
||||||
|
entity2.Date = entity.Date.AddDays(datesRangeExpected);
|
||||||
|
|
||||||
|
var dbset = dbContext.Set<TEntity>();
|
||||||
|
dbset.Add(entity);
|
||||||
|
dbset.Add(entity2);
|
||||||
|
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var response = await timeSeriesClient.GetDatesRange(new CancellationToken());
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.NotNull(response);
|
||||||
|
|
||||||
|
var datesRangeActual = (response.To - response.From).Days;
|
||||||
|
Assert.Equal(datesRangeExpected, datesRangeActual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task GetResampledDataSuccess(TEntity entity)
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
var approxPointsCount = 10;
|
||||||
|
var differenceBetweenStartAndEndDays = 50;
|
||||||
|
|
||||||
|
var entities = new List<TEntity>();
|
||||||
|
for (var i = 1; i <= differenceBetweenStartAndEndDays; i++)
|
||||||
|
{
|
||||||
|
var entity2 = entity.Adapt<TEntity>();
|
||||||
|
entity2.Date = entity.Date.AddDays(i - 1);
|
||||||
|
|
||||||
|
entities.Add(entity2);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dbset = dbContext.Set<TEntity>();
|
||||||
|
dbset.AddRange(entities);
|
||||||
|
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var response = await timeSeriesClient.GetResampledData(entity.Date.AddMinutes(-1), differenceBetweenStartAndEndDays * 24 * 60 * 60 + 60, approxPointsCount, new CancellationToken());
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.NotNull(response);
|
||||||
|
|
||||||
|
var ratio = entities.Count / approxPointsCount;
|
||||||
|
if (ratio > 1)
|
||||||
|
{
|
||||||
|
var expectedResampledCount = entities
|
||||||
|
.Where((_, index) => index % ratio == 0)
|
||||||
|
.Count();
|
||||||
|
|
||||||
|
Assert.Equal(expectedResampledCount, response.Count());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Equal(entities.Count(), response.Count());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,211 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using DD.Persistence.Client;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using Xunit;
|
||||||
|
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||||
|
using DD.Persistence.Client.Clients;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace DD.Persistence.IntegrationTests.Controllers;
|
||||||
|
public class TimestampedSetControllerTest : BaseIntegrationTest
|
||||||
|
{
|
||||||
|
private readonly ITimestampedSetClient client;
|
||||||
|
|
||||||
|
public TimestampedSetControllerTest(WebAppFactoryFixture factory) : base(factory)
|
||||||
|
{
|
||||||
|
var refitClientFactory = scope.ServiceProvider
|
||||||
|
.GetRequiredService<IRefitClientFactory<IRefitTimestampedSetClient>>();
|
||||||
|
var logger = scope.ServiceProvider.GetRequiredService<ILogger<TimestampedSetClient>>();
|
||||||
|
|
||||||
|
client = scope.ServiceProvider
|
||||||
|
.GetRequiredService<ITimestampedSetClient>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task InsertRange()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
Guid idDiscriminator = Guid.NewGuid();
|
||||||
|
IEnumerable<TimestampedSetDto> testSets = Generate(10, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
|
||||||
|
|
||||||
|
// act
|
||||||
|
var response = await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.Equal(testSets.Count(), response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_without_filter()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
Guid idDiscriminator = Guid.NewGuid();
|
||||||
|
int count = 10;
|
||||||
|
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
|
||||||
|
await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
|
||||||
|
|
||||||
|
// act
|
||||||
|
var response = await client.Get(idDiscriminator, null, null, 0, int.MaxValue, CancellationToken.None);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.NotNull(response);
|
||||||
|
Assert.Equal(count, response.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_with_filter_props()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
Guid idDiscriminator = Guid.NewGuid();
|
||||||
|
int count = 10;
|
||||||
|
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
|
||||||
|
await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
|
||||||
|
string[] props = ["A"];
|
||||||
|
|
||||||
|
// act
|
||||||
|
var response = await client.Get(idDiscriminator, null, props, 0, int.MaxValue, new CancellationToken());
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.NotNull(response);
|
||||||
|
Assert.Equal(count, response.Count());
|
||||||
|
foreach (var item in response)
|
||||||
|
{
|
||||||
|
Assert.Single(item.Set);
|
||||||
|
var kv = item.Set.First();
|
||||||
|
Assert.Equal("A", kv.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_geDate()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
Guid idDiscriminator = Guid.NewGuid();
|
||||||
|
int count = 10;
|
||||||
|
var dateMin = DateTimeOffset.Now;
|
||||||
|
var dateMax = DateTimeOffset.Now.AddSeconds(count);
|
||||||
|
IEnumerable<TimestampedSetDto> testSets = Generate(count, dateMin.ToOffset(TimeSpan.FromHours(7)));
|
||||||
|
var insertResponse = await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
|
||||||
|
var tail = testSets.OrderBy(t => t.Timestamp).Skip(count / 2).Take(int.MaxValue);
|
||||||
|
var geDate = tail.First().Timestamp;
|
||||||
|
var tolerance = TimeSpan.FromSeconds(1);
|
||||||
|
var expectedCount = tail.Count();
|
||||||
|
|
||||||
|
// act
|
||||||
|
var response = await client.Get(idDiscriminator, geDate, null, 0, int.MaxValue, CancellationToken.None);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.NotNull(response);
|
||||||
|
Assert.Equal(expectedCount, response.Count());
|
||||||
|
var minDate = response.Min(t => t.Timestamp);
|
||||||
|
Assert.Equal(geDate, geDate, tolerance);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_with_skip_take()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
Guid idDiscriminator = Guid.NewGuid();
|
||||||
|
int count = 10;
|
||||||
|
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
|
||||||
|
await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
|
||||||
|
var expectedCount = count / 2;
|
||||||
|
|
||||||
|
// act
|
||||||
|
var response = await client.Get(idDiscriminator, null, null, 2, expectedCount, new CancellationToken());
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.NotNull(response);
|
||||||
|
Assert.Equal(expectedCount, response.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_with_big_skip_take()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
Guid idDiscriminator = Guid.NewGuid();
|
||||||
|
var expectedCount = 1;
|
||||||
|
int count = 10 + expectedCount;
|
||||||
|
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
|
||||||
|
await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
|
||||||
|
|
||||||
|
// act
|
||||||
|
var response = await client.Get(idDiscriminator, null, null, count - expectedCount, count, new CancellationToken());
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.NotNull(response);
|
||||||
|
Assert.Equal(expectedCount, response.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetLast()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
Guid idDiscriminator = Guid.NewGuid();
|
||||||
|
int count = 10;
|
||||||
|
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
|
||||||
|
await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
|
||||||
|
var expectedCount = 8;
|
||||||
|
|
||||||
|
// act
|
||||||
|
var response = await client.GetLast(idDiscriminator, null, expectedCount, new CancellationToken());
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.NotNull(response);
|
||||||
|
Assert.Equal(expectedCount, response.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetDatesRange()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
Guid idDiscriminator = Guid.NewGuid();
|
||||||
|
int count = 10;
|
||||||
|
var dateMin = DateTimeOffset.Now;
|
||||||
|
var dateMax = DateTimeOffset.Now.AddSeconds(count - 1);
|
||||||
|
IEnumerable<TimestampedSetDto> testSets = Generate(count, dateMin.ToOffset(TimeSpan.FromHours(7)));
|
||||||
|
await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
|
||||||
|
var tolerance = TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
|
// act
|
||||||
|
var response = await client.GetDatesRange(idDiscriminator, new CancellationToken());
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.NotNull(response);
|
||||||
|
Assert.Equal(dateMin, response.From, tolerance);
|
||||||
|
Assert.Equal(dateMax, response.To, tolerance);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Count()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
Guid idDiscriminator = Guid.NewGuid();
|
||||||
|
int count = 144;
|
||||||
|
IEnumerable<TimestampedSetDto> testSets = Generate(count, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
|
||||||
|
await client.AddRange(idDiscriminator, testSets, CancellationToken.None);
|
||||||
|
|
||||||
|
// act
|
||||||
|
var response = await client.Count(idDiscriminator, new CancellationToken());
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.Equal(count, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<TimestampedSetDto> Generate(int n, DateTimeOffset from)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
yield return new TimestampedSetDto
|
||||||
|
(
|
||||||
|
from.AddSeconds(i),
|
||||||
|
new Dictionary<string, object>{
|
||||||
|
{"A", i },
|
||||||
|
{"B", i * 1.1 },
|
||||||
|
{"C", $"Any{i}" },
|
||||||
|
{"D", DateTimeOffset.Now},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,414 +0,0 @@
|
|||||||
using DD.Persistence.Client;
|
|
||||||
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;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using System.Text.Json;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace DD.Persistence.IntegrationTests.Controllers;
|
|
||||||
public class TimestampedValuesControllerTest : BaseIntegrationTest
|
|
||||||
{
|
|
||||||
private readonly ITimestampedValuesClient timestampedValuesClient;
|
|
||||||
private readonly IMemoryCache memoryCache;
|
|
||||||
private IEnumerable<Guid> discriminatorIds = [];
|
|
||||||
|
|
||||||
public TimestampedValuesControllerTest(WebAppFactoryFixture factory) : base(factory)
|
|
||||||
{
|
|
||||||
var refitClientFactory = scope.ServiceProvider
|
|
||||||
.GetRequiredService<IRefitClientFactory<IRefitTimestampedValuesClient>>();
|
|
||||||
var logger = scope.ServiceProvider.GetRequiredService<ILogger<TimestampedValuesClient>>();
|
|
||||||
|
|
||||||
timestampedValuesClient = scope.ServiceProvider
|
|
||||||
.GetRequiredService<ITimestampedValuesClient>();
|
|
||||||
memoryCache = scope.ServiceProvider.GetRequiredService<IMemoryCache>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task AddRange_returns_success()
|
|
||||||
{
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
await AddRange(discriminatorId);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Get_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 Get_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<string>() { "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()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
var timestampBegin = DateTimeOffset.UtcNow.AddDays(-1);
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.GetGtDate(discriminatorId, timestampBegin, CancellationToken.None);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Null(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetGtDate_AfterSave_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
var dtos = await AddRange(discriminatorId);
|
|
||||||
var timestampBegin = DateTimeOffset.UtcNow.AddSeconds(-5);
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.GetGtDate(discriminatorId, timestampBegin, CancellationToken.None);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.NotNull(response);
|
|
||||||
Assert.NotEmpty(response);
|
|
||||||
|
|
||||||
var expectedCount = dtos.Count(dto => dto.Timestamp.ToUniversalTime() > timestampBegin);
|
|
||||||
var actualCount = response.Count();
|
|
||||||
Assert.Equal(expectedCount, actualCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetFirst_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
var take = 1;
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.GetFirst(discriminatorId, take, CancellationToken.None);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Null(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetFirst_AfterSave_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
var dtos = await AddRange(discriminatorId);
|
|
||||||
var take = 1;
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.GetFirst(discriminatorId, take, CancellationToken.None);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.NotNull(response);
|
|
||||||
Assert.NotEmpty(response);
|
|
||||||
|
|
||||||
var expectedTimestampString = dtos
|
|
||||||
.OrderBy(dto => dto.Timestamp)
|
|
||||||
.First().Timestamp
|
|
||||||
.ToUniversalTime()
|
|
||||||
.ToString();
|
|
||||||
var actualTimestampString = response
|
|
||||||
.First().Timestamp
|
|
||||||
.ToUniversalTime()
|
|
||||||
.ToString();
|
|
||||||
Assert.Equal(expectedTimestampString, actualTimestampString);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetLast_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
var take = 1;
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.GetLast(discriminatorId, take, CancellationToken.None);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Null(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetLast_AfterSave_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
var dtos = await AddRange(discriminatorId);
|
|
||||||
var take = 1;
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.GetLast(discriminatorId, take, CancellationToken.None);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.NotNull(response);
|
|
||||||
Assert.NotEmpty(response);
|
|
||||||
|
|
||||||
var expectedTimestampString = dtos
|
|
||||||
.OrderByDescending(dto => dto.Timestamp)
|
|
||||||
.First().Timestamp
|
|
||||||
.ToUniversalTime()
|
|
||||||
.ToString();
|
|
||||||
var actualTimestampString = response
|
|
||||||
.First().Timestamp
|
|
||||||
.ToUniversalTime()
|
|
||||||
.ToString();
|
|
||||||
Assert.Equal(expectedTimestampString, actualTimestampString);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetResampledData_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
var timestampBegin = DateTimeOffset.UtcNow;
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.GetResampledData(discriminatorId, timestampBegin);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Null(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetResampledData_AfterSave_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
var count = 2048;
|
|
||||||
var timestampBegin = DateTimeOffset.UtcNow;
|
|
||||||
var dtos = await AddRange(discriminatorId, count);
|
|
||||||
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.GetResampledData(discriminatorId, timestampBegin, count);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.NotNull(response);
|
|
||||||
Assert.NotEmpty(response);
|
|
||||||
|
|
||||||
var expectedCount = count / 2;
|
|
||||||
var actualCount = response.Count();
|
|
||||||
Assert.Equal(expectedCount, actualCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Count_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.Count(discriminatorId, CancellationToken.None);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(0, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Count_AfterSave_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
var dtos = await AddRange(discriminatorId);
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.Count(discriminatorId, CancellationToken.None);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
var expectedCount = dtos.Count();
|
|
||||||
Assert.Equal(expectedCount, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetDatesRange_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.GetDatesRange(discriminatorId, CancellationToken.None);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Null(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetDatesRange_AfterSave_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
Cleanup();
|
|
||||||
|
|
||||||
var discriminatorId = Guid.NewGuid();
|
|
||||||
discriminatorIds.Append(discriminatorId);
|
|
||||||
|
|
||||||
var dtos = await AddRange(discriminatorId);
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await timestampedValuesClient.GetDatesRange(discriminatorId, CancellationToken.None);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.NotNull(response);
|
|
||||||
|
|
||||||
var expectedDateFromString = dtos
|
|
||||||
.OrderBy(dto => dto.Timestamp)
|
|
||||||
.First().Timestamp
|
|
||||||
.ToUniversalTime()
|
|
||||||
.ToString();
|
|
||||||
var actualDateFromString = response.From
|
|
||||||
.ToUniversalTime()
|
|
||||||
.ToString();
|
|
||||||
Assert.Equal(expectedDateFromString, actualDateFromString);
|
|
||||||
|
|
||||||
var expectedDateToString = dtos
|
|
||||||
.OrderByDescending(dto => dto.Timestamp)
|
|
||||||
.First().Timestamp
|
|
||||||
.ToUniversalTime()
|
|
||||||
.ToString();
|
|
||||||
var actualDateToString = response.To
|
|
||||||
.ToUniversalTime()
|
|
||||||
.ToString();
|
|
||||||
Assert.Equal(expectedDateToString, actualDateToString);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IEnumerable<TimestampedValuesDto>> AddRange(Guid discriminatorId, int countToCreate = 10)
|
|
||||||
{
|
|
||||||
// arrange
|
|
||||||
IEnumerable<TimestampedValuesDto> generatedDtos = Generate(countToCreate, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
|
|
||||||
|
|
||||||
// act
|
|
||||||
var response = await timestampedValuesClient.AddRange(discriminatorId, generatedDtos, CancellationToken.None);
|
|
||||||
|
|
||||||
// assert
|
|
||||||
Assert.Equal(generatedDtos.Count(), response);
|
|
||||||
|
|
||||||
return generatedDtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<TimestampedValuesDto> Generate(int countToCreate, DateTimeOffset from)
|
|
||||||
{
|
|
||||||
var result = new List<TimestampedValuesDto>();
|
|
||||||
for (int i = 0; i < countToCreate; i++)
|
|
||||||
{
|
|
||||||
var values = new Dictionary<string, object>()
|
|
||||||
{
|
|
||||||
{ "A", i },
|
|
||||||
{ "B", i * 1.1 },
|
|
||||||
{ "C", $"Any{i}" },
|
|
||||||
{ "D", DateTimeOffset.Now },
|
|
||||||
};
|
|
||||||
|
|
||||||
yield return new TimestampedValuesDto()
|
|
||||||
{
|
|
||||||
Timestamp = from.AddSeconds(i),
|
|
||||||
Values = values
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Cleanup()
|
|
||||||
{
|
|
||||||
discriminatorIds = [];
|
|
||||||
dbContext.CleanupDbSet<TimestampedValues>();
|
|
||||||
dbContext.CleanupDbSet<DataScheme>();
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
|
|||||||
using DD.Persistence.API;
|
using DD.Persistence.API;
|
||||||
using DD.Persistence.Client;
|
using DD.Persistence.Client;
|
||||||
using DD.Persistence.Database.Model;
|
using DD.Persistence.Database.Model;
|
||||||
|
using DD.Persistence.Database.Postgres;
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
using DD.Persistence.App;
|
using DD.Persistence.App;
|
||||||
using DD.Persistence.Client.Helpers;
|
using DD.Persistence.Client.Helpers;
|
||||||
using DD.Persistence.Factories;
|
using DD.Persistence.Factories;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using DD.Persistence.Database.Postgres.Extensions;
|
|
||||||
|
|
||||||
namespace DD.Persistence.IntegrationTests;
|
namespace DD.Persistence.IntegrationTests;
|
||||||
public class WebAppFactoryFixture : WebApplicationFactory<Program>
|
public class WebAppFactoryFixture : WebApplicationFactory<Program>
|
||||||
|
@ -38,5 +38,5 @@ public class ChangeLogDto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Объект записи
|
/// Объект записи
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ChangeLogValuesDto Value { get; set; } = default!;
|
public DataWithWellDepthAndSectionDto Value { get; set; } = default!;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
namespace DD.Persistence.Models;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Dto для хранения записей, содержащих начальную и конечную глубину забоя, а также секцию
|
|
||||||
/// </summary>
|
|
||||||
public class ChangeLogValuesDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Ключ записи
|
|
||||||
/// </summary>
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Объект записи
|
|
||||||
/// </summary>
|
|
||||||
public required IDictionary<string, object> Value { get; set; }
|
|
||||||
}
|
|
41
DD.Persistence.Models/DataSaubDto.cs
Normal file
41
DD.Persistence.Models/DataSaubDto.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
namespace DD.Persistence.Models;
|
||||||
|
public class DataSaubDto : ITimeSeriesAbstractDto
|
||||||
|
{
|
||||||
|
public DateTimeOffset Date { get; set; } = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
|
public int? Mode { get; set; }
|
||||||
|
|
||||||
|
public string? User { get; set; }
|
||||||
|
|
||||||
|
public double? WellDepth { get; set; }
|
||||||
|
|
||||||
|
public double? BitDepth { get; set; }
|
||||||
|
|
||||||
|
public double? BlockPosition { get; set; }
|
||||||
|
|
||||||
|
public double? BlockSpeed { get; set; }
|
||||||
|
|
||||||
|
public double? Pressure { get; set; }
|
||||||
|
|
||||||
|
public double? AxialLoad { get; set; }
|
||||||
|
|
||||||
|
public double? HookWeight { get; set; }
|
||||||
|
|
||||||
|
public double? RotorTorque { get; set; }
|
||||||
|
|
||||||
|
public double? RotorSpeed { get; set; }
|
||||||
|
|
||||||
|
public double? Flow { get; set; }
|
||||||
|
|
||||||
|
public short MseState { get; set; }
|
||||||
|
|
||||||
|
public int IdFeedRegulator { get; set; }
|
||||||
|
|
||||||
|
public double? Mse { get; set; }
|
||||||
|
|
||||||
|
public double? Pump0Flow { get; set; }
|
||||||
|
|
||||||
|
public double? Pump1Flow { get; set; }
|
||||||
|
|
||||||
|
public double? Pump2Flow { get; set; }
|
||||||
|
}
|
@ -1,17 +0,0 @@
|
|||||||
namespace DD.Persistence.Models;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Схема для набора данных
|
|
||||||
/// </summary>
|
|
||||||
public class DataSchemeDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Дискриминатор
|
|
||||||
/// </summary>
|
|
||||||
public Guid DiscriminatorId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Наименования полей
|
|
||||||
/// </summary>
|
|
||||||
public string[] PropNames { get; set; } = [];
|
|
||||||
}
|
|
@ -13,7 +13,7 @@ public class DataSourceSystemDto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Наименование
|
/// Наименование
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; } = string.Empty;
|
public required string Name { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Описание
|
/// Описание
|
||||||
|
32
DD.Persistence.Models/DataWithWellDepthAndSectionDto.cs
Normal file
32
DD.Persistence.Models/DataWithWellDepthAndSectionDto.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
namespace DD.Persistence.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dto для хранения записей, содержащих начальную и конечную глубину забоя, а также секцию
|
||||||
|
/// </summary>
|
||||||
|
public class DataWithWellDepthAndSectionDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Ключ записи
|
||||||
|
/// </summary>
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Глубина забоя на дату начала интервала
|
||||||
|
/// </summary>
|
||||||
|
public double DepthStart { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Глубина забоя на дату окончания интервала
|
||||||
|
/// </summary>
|
||||||
|
public double DepthEnd { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ключ секции
|
||||||
|
/// </summary>
|
||||||
|
public Guid IdSection { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Объект записи
|
||||||
|
/// </summary>
|
||||||
|
public required IDictionary<string, object> Value { get; set; }
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
namespace DD.Persistence.Models.Common;
|
namespace DD.Persistence.Models;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Диапазон дат
|
/// Диапазон дат
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
namespace DD.Persistence.ModelsAbstractions;
|
namespace DD.Persistence.Models;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Интерфейс, описывающий временные данные
|
/// Интерфейс, описывающий временные данные
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITimestampAbstractDto
|
public interface ITimeSeriesAbstractDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// временная отметка
|
/// временная отметка
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DateTimeOffset Timestamp { get; set; }
|
DateTimeOffset Date { get; set; }
|
||||||
}
|
}
|
||||||
|
9
DD.Persistence.Models/IWithSectionPart.cs
Normal file
9
DD.Persistence.Models/IWithSectionPart.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace DD.Persistence.Models;
|
||||||
|
public interface IWithSectionPart
|
||||||
|
{
|
||||||
|
public double DepthStart { get; set; }
|
||||||
|
|
||||||
|
public double DepthEnd { get; set; }
|
||||||
|
|
||||||
|
public Guid IdSection { get; set; }
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
namespace DD.Persistence.Models.Common;
|
namespace DD.Persistence.Models;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Контейнер для поддержки постраничного просмотра таблиц
|
/// Контейнер для поддержки постраничного просмотра таблиц
|
||||||
|
22
DD.Persistence.Models/Requests/SectionPartRequest.cs
Normal file
22
DD.Persistence.Models/Requests/SectionPartRequest.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
namespace DD.Persistence.Models.Requests;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Запрос для фильтрации данных по секции и глубине
|
||||||
|
/// </summary>
|
||||||
|
public class SectionPartRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Глубина забоя на дату начала интервала
|
||||||
|
/// </summary>
|
||||||
|
public double? DepthStart { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Глубина забоя на дату окончания интервала
|
||||||
|
/// </summary>
|
||||||
|
public double? DepthEnd { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ключ секции
|
||||||
|
/// </summary>
|
||||||
|
public Guid? IdSection { get; set; }
|
||||||
|
}
|
@ -8,7 +8,7 @@ public class SetpointLogDto : SetpointValueDto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Дата сохранения уставки
|
/// Дата сохранения уставки
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTimeOffset Timestamp { get; set; }
|
public DateTimeOffset Created { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ключ пользователя
|
/// Ключ пользователя
|
||||||
|
8
DD.Persistence.Models/TimestampedSetDto.cs
Normal file
8
DD.Persistence.Models/TimestampedSetDto.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace DD.Persistence.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// набор данных с отметкой времени
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Timestamp">отметка времени</param>
|
||||||
|
/// <param name="Set">набор данных</param>
|
||||||
|
public record TimestampedSetDto(DateTimeOffset Timestamp, IDictionary<string, object> Set);
|
@ -1,19 +0,0 @@
|
|||||||
using DD.Persistence.ModelsAbstractions;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Models;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Набор данных с отметкой времени
|
|
||||||
/// </summary>
|
|
||||||
public class TimestampedValuesDto : ITimestampAbstractDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Временная отметка
|
|
||||||
/// </summary>
|
|
||||||
public DateTimeOffset Timestamp { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Набор данных
|
|
||||||
/// </summary>
|
|
||||||
public Dictionary<string, object> Values { get; set; } = [];
|
|
||||||
}
|
|
@ -1,10 +1,10 @@
|
|||||||
using DD.Persistence.Database.Entity;
|
using Mapster;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using DD.Persistence.Database.Model;
|
||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Repositories;
|
using DD.Persistence.Repositories;
|
||||||
using DD.Persistence.Repository.Repositories;
|
using DD.Persistence.Repository.Repositories;
|
||||||
using DD.Persistence.Repository.RepositoriesCached;
|
using DD.Persistence.Database.Entity;
|
||||||
using Mapster;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace DD.Persistence.Repository;
|
namespace DD.Persistence.Repository;
|
||||||
@ -17,8 +17,11 @@ public static class DependencyInjection
|
|||||||
.Ignore(dest => dest.System, dest => dest.SystemId);
|
.Ignore(dest => dest.System, dest => dest.SystemId);
|
||||||
|
|
||||||
TypeAdapterConfig<ChangeLog, ChangeLogDto>.NewConfig()
|
TypeAdapterConfig<ChangeLog, ChangeLogDto>.NewConfig()
|
||||||
.Map(dest => dest.Value, src => new ChangeLogValuesDto()
|
.Map(dest => dest.Value, src => new DataWithWellDepthAndSectionDto()
|
||||||
{
|
{
|
||||||
|
DepthEnd = src.DepthEnd,
|
||||||
|
DepthStart = src.DepthStart,
|
||||||
|
IdSection = src.IdSection,
|
||||||
Value = src.Value,
|
Value = src.Value,
|
||||||
Id = src.Id
|
Id = src.Id
|
||||||
});
|
});
|
||||||
@ -32,14 +35,15 @@ public static class DependencyInjection
|
|||||||
|
|
||||||
MapsterSetup();
|
MapsterSetup();
|
||||||
|
|
||||||
|
services.AddTransient<ITimeSeriesDataRepository<DataSaubDto>, TimeSeriesDataRepository<DataSaub, DataSaubDto>>();
|
||||||
services.AddTransient<ISetpointRepository, SetpointRepository>();
|
services.AddTransient<ISetpointRepository, SetpointRepository>();
|
||||||
|
services.AddTransient<ITimeSeriesDataRepository<DataSaubDto>, TimeSeriesDataCachedRepository<DataSaub, DataSaubDto>>();
|
||||||
services.AddTransient<IChangeLogRepository, ChangeLogRepository>();
|
services.AddTransient<IChangeLogRepository, ChangeLogRepository>();
|
||||||
services.AddTransient<ITimestampedValuesRepository, TimestampedValuesRepository>();
|
services.AddTransient<ITimestampedSetRepository, TimestampedSetRepository>();
|
||||||
services.AddTransient<ITechMessagesRepository, TechMessagesRepository>();
|
services.AddTransient<ITechMessagesRepository, TechMessagesRepository>();
|
||||||
services.AddTransient<IParameterRepository, ParameterRepository>();
|
services.AddTransient<IParameterRepository, ParameterRepository>();
|
||||||
services.AddTransient<IDataSourceSystemRepository, DataSourceSystemCachedRepository>();
|
services.AddTransient<IDataSourceSystemRepository, DataSourceSystemCachedRepository>();
|
||||||
services.AddTransient<IDataSchemeRepository, DataSchemeCachedRepository>();
|
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using DD.Persistence.Database.Model;
|
||||||
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Requests;
|
using DD.Persistence.Models.Requests;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using DD.Persistence.ModelsAbstractions;
|
|
||||||
using DD.Persistence.Database.EntityAbstractions;
|
|
||||||
using DD.Persistence.Extensions;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Repository;
|
namespace DD.Persistence.Repository;
|
||||||
|
|
||||||
@ -12,6 +10,25 @@ namespace DD.Persistence.Repository;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class QueryBuilders
|
public static class QueryBuilders
|
||||||
{
|
{
|
||||||
|
public static IQueryable<TEntity> Apply<TEntity>(this IQueryable<TEntity> 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<TEntity> Apply<TEntity>(this IQueryable<TEntity> query, DateTimeOffset momentUtc)
|
public static IQueryable<TEntity> Apply<TEntity>(this IQueryable<TEntity> query, DateTimeOffset momentUtc)
|
||||||
where TEntity : class, IChangeLog
|
where TEntity : class, IChangeLog
|
||||||
{
|
{
|
||||||
@ -30,10 +47,17 @@ public static class QueryBuilders
|
|||||||
PaginationRequest request,
|
PaginationRequest request,
|
||||||
Func<TEntity, TDto> Convert,
|
Func<TEntity, TDto> Convert,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
where TEntity : class
|
where TEntity : class, IWithSectionPart
|
||||||
where TDto : class
|
where TDto : class
|
||||||
{
|
{
|
||||||
if (!String.IsNullOrEmpty(request.SortSettings))
|
if (String.IsNullOrEmpty(request.SortSettings))
|
||||||
|
{
|
||||||
|
query = query
|
||||||
|
.OrderBy(e => e.IdSection)
|
||||||
|
.ThenBy(e => e.DepthStart)
|
||||||
|
.ThenBy(e => e.DepthEnd);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
query = query.SortBy(request.SortSettings);
|
query = query.SortBy(request.SortSettings);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
using DD.Persistence.Database.Entity;
|
using Mapster;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using DD.Persistence.Database.Model;
|
||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using DD.Persistence.Models.Requests;
|
using DD.Persistence.Models.Requests;
|
||||||
using DD.Persistence.Repositories;
|
using DD.Persistence.Repositories;
|
||||||
using Mapster;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using UuidExtensions;
|
using UuidExtensions;
|
||||||
|
|
||||||
namespace DD.Persistence.Repository.Repositories;
|
namespace DD.Persistence.Repository.Repositories;
|
||||||
@ -17,7 +16,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
|||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token)
|
public async Task<int> AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
|
||||||
{
|
{
|
||||||
var entities = new List<ChangeLog>();
|
var entities = new List<ChangeLog>();
|
||||||
foreach (var dto in dtos)
|
foreach (var dto in dtos)
|
||||||
@ -76,7 +75,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
|||||||
return await db.SaveChangesAsync(token);
|
return await db.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token)
|
public async Task<int> ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
|
||||||
{
|
{
|
||||||
var result = 0;
|
var result = 0;
|
||||||
|
|
||||||
@ -91,7 +90,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> UpdateRange(Guid idEditor, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token)
|
public async Task<int> UpdateRange(Guid idEditor, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
|
||||||
{
|
{
|
||||||
var dbSet = db.Set<ChangeLog>();
|
var dbSet = db.Set<ChangeLog>();
|
||||||
|
|
||||||
@ -127,14 +126,16 @@ public class ChangeLogRepository : IChangeLogRepository
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PaginationContainer<ChangeLogValuesDto>> GetByDate(
|
public async Task<PaginationContainer<DataWithWellDepthAndSectionDto>> GetByDate(
|
||||||
Guid idDiscriminator,
|
Guid idDiscriminator,
|
||||||
DateTimeOffset momentUtc,
|
DateTimeOffset momentUtc,
|
||||||
|
SectionPartRequest filterRequest,
|
||||||
PaginationRequest paginationRequest,
|
PaginationRequest paginationRequest,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
var query = CreateQuery(idDiscriminator);
|
var query = CreateQuery(idDiscriminator);
|
||||||
query = query.Apply(momentUtc);
|
query = query.Apply(momentUtc);
|
||||||
|
query = query.Apply(filterRequest);
|
||||||
|
|
||||||
var result = await query.ApplyPagination(paginationRequest, Convert, token);
|
var result = await query.ApplyPagination(paginationRequest, Convert, token);
|
||||||
|
|
||||||
@ -194,7 +195,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
|||||||
return datesOnly;
|
return datesOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ChangeLog CreateEntityFromDto(Guid idAuthor, Guid idDiscriminator, ChangeLogValuesDto dto)
|
private static ChangeLog CreateEntityFromDto(Guid idAuthor, Guid idDiscriminator, DataWithWellDepthAndSectionDto dto)
|
||||||
{
|
{
|
||||||
var entity = new ChangeLog()
|
var entity = new ChangeLog()
|
||||||
{
|
{
|
||||||
@ -204,13 +205,16 @@ public class ChangeLogRepository : IChangeLogRepository
|
|||||||
IdDiscriminator = idDiscriminator,
|
IdDiscriminator = idDiscriminator,
|
||||||
IdEditor = idAuthor,
|
IdEditor = idAuthor,
|
||||||
|
|
||||||
Value = dto.Value
|
Value = dto.Value,
|
||||||
|
IdSection = dto.IdSection,
|
||||||
|
DepthStart = dto.DepthStart,
|
||||||
|
DepthEnd = dto.DepthEnd,
|
||||||
};
|
};
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<ChangeLogValuesDto>> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token)
|
public async Task<IEnumerable<DataWithWellDepthAndSectionDto>> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token)
|
||||||
{
|
{
|
||||||
var date = dateBegin.ToUniversalTime();
|
var date = dateBegin.ToUniversalTime();
|
||||||
var query = this.db.Set<ChangeLog>()
|
var query = this.db.Set<ChangeLog>()
|
||||||
@ -251,5 +255,5 @@ public class ChangeLogRepository : IChangeLogRepository
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangeLogValuesDto Convert(ChangeLog entity) => entity.Adapt<ChangeLogValuesDto>();
|
private DataWithWellDepthAndSectionDto Convert(ChangeLog entity) => entity.Adapt<DataWithWellDepthAndSectionDto>();
|
||||||
}
|
}
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
using DD.Persistence.Database.Entity;
|
|
||||||
using DD.Persistence.Models;
|
|
||||||
using DD.Persistence.Repositories;
|
|
||||||
using Mapster;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Repository.Repositories;
|
|
||||||
public class DataSchemeRepository : IDataSchemeRepository
|
|
||||||
{
|
|
||||||
protected DbContext db;
|
|
||||||
public DataSchemeRepository(DbContext db)
|
|
||||||
{
|
|
||||||
this.db = db;
|
|
||||||
}
|
|
||||||
protected virtual IQueryable<DataScheme> GetQueryReadOnly() => db.Set<DataScheme>();
|
|
||||||
|
|
||||||
public virtual async Task Add(DataSchemeDto dataSourceSystemDto, CancellationToken token)
|
|
||||||
{
|
|
||||||
var entity = dataSourceSystemDto.Adapt<DataScheme>();
|
|
||||||
|
|
||||||
await db.Set<DataScheme>().AddAsync(entity, token);
|
|
||||||
await db.SaveChangesAsync(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual async Task<DataSchemeDto?> Get(Guid dataSchemeId, CancellationToken token)
|
|
||||||
{
|
|
||||||
var query = GetQueryReadOnly()
|
|
||||||
.Where(e => e.DiscriminatorId == dataSchemeId);
|
|
||||||
var entity = await query.ToArrayAsync();
|
|
||||||
var dto = entity.Select(e => e.Adapt<DataSchemeDto>()).FirstOrDefault();
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +1,13 @@
|
|||||||
using DD.Persistence.Database.Entity;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using DD.Persistence.Models;
|
|
||||||
using DD.Persistence.Repository.Repositories;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
|
||||||
namespace DD.Persistence.Repository.RepositoriesCached;
|
namespace DD.Persistence.Repository.Repositories;
|
||||||
public class DataSourceSystemCachedRepository : DataSourceSystemRepository
|
public class DataSourceSystemCachedRepository : DataSourceSystemRepository
|
||||||
{
|
{
|
||||||
private static readonly string SystemCacheKey = $"{typeof(DataSourceSystem).FullName}CacheKey";
|
private static readonly string SystemCacheKey = $"{typeof(Database.Entity.DataSourceSystem).FullName}CacheKey";
|
||||||
private readonly IMemoryCache memoryCache;
|
private readonly IMemoryCache memoryCache;
|
||||||
|
private const int CacheExpirationInMinutes = 60;
|
||||||
private readonly TimeSpan? AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60);
|
private readonly TimeSpan? AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60);
|
||||||
|
|
||||||
public DataSourceSystemCachedRepository(DbContext db, IMemoryCache memoryCache) : base(db)
|
public DataSourceSystemCachedRepository(DbContext db, IMemoryCache memoryCache) : base(db)
|
@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using DD.Persistence.Database.Entity;
|
using DD.Persistence.Database.Entity;
|
||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Repositories;
|
using DD.Persistence.Repositories;
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Repository.Repositories;
|
namespace DD.Persistence.Repository.Repositories;
|
||||||
public class ParameterRepository : IParameterRepository
|
public class ParameterRepository : IParameterRepository
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
using DD.Persistence.Database.Entity;
|
using Mapster;
|
||||||
using DD.Persistence.Models;
|
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using DD.Persistence.Repositories;
|
|
||||||
using Mapster;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using DD.Persistence.Database.Model;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using DD.Persistence.Repositories;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace DD.Persistence.Repository.Repositories
|
namespace DD.Persistence.Repository.Repositories
|
||||||
@ -27,7 +26,7 @@ namespace DD.Persistence.Repository.Repositories
|
|||||||
var entities = await query
|
var entities = await query
|
||||||
.Where(e => setpointKeys.Contains(e.Key))
|
.Where(e => setpointKeys.Contains(e.Key))
|
||||||
.GroupBy(e => e.Key)
|
.GroupBy(e => e.Key)
|
||||||
.Select(g => g.OrderByDescending(x => x.Timestamp).FirstOrDefault())
|
.Select(g => g.OrderByDescending(x => x.Created).FirstOrDefault())
|
||||||
.ToArrayAsync(token);
|
.ToArrayAsync(token);
|
||||||
|
|
||||||
var dtos = entities.Select(e => e.Adapt<SetpointValueDto>());
|
var dtos = entities.Select(e => e.Adapt<SetpointValueDto>());
|
||||||
@ -40,7 +39,7 @@ namespace DD.Persistence.Repository.Repositories
|
|||||||
var entities = await query
|
var entities = await query
|
||||||
.Where(e => setpointKeys.Contains(e.Key))
|
.Where(e => setpointKeys.Contains(e.Key))
|
||||||
.GroupBy(e => e.Key)
|
.GroupBy(e => e.Key)
|
||||||
.Select(g => g.OrderByDescending(x => x.Timestamp).FirstOrDefault())
|
.Select(g => g.OrderByDescending(x => x.Created).FirstOrDefault())
|
||||||
.ToDictionaryAsync(x=> x.Key, x => (object)x.Value, token);
|
.ToDictionaryAsync(x=> x.Key, x => (object)x.Value, token);
|
||||||
|
|
||||||
return entities;
|
return entities;
|
||||||
@ -54,8 +53,8 @@ namespace DD.Persistence.Repository.Repositories
|
|||||||
.ToArrayAsync(token);
|
.ToArrayAsync(token);
|
||||||
var filteredEntities = entities
|
var filteredEntities = entities
|
||||||
.GroupBy(e => e.Key)
|
.GroupBy(e => e.Key)
|
||||||
.Select(e => e.OrderBy(o => o.Timestamp))
|
.Select(e => e.OrderBy(o => o.Created))
|
||||||
.Select(e => e.Where(e => e.Timestamp <= historyMoment).Last());
|
.Select(e => e.Where(e => e.Created <= historyMoment).Last());
|
||||||
var dtos = filteredEntities
|
var dtos = filteredEntities
|
||||||
.Select(e => e.Adapt<SetpointValueDto>());
|
.Select(e => e.Adapt<SetpointValueDto>());
|
||||||
|
|
||||||
@ -66,7 +65,7 @@ namespace DD.Persistence.Repository.Repositories
|
|||||||
{
|
{
|
||||||
var query = GetQueryReadOnly();
|
var query = GetQueryReadOnly();
|
||||||
var entities = await query
|
var entities = await query
|
||||||
.Where(e => e.Timestamp >= dateBegin)
|
.Where(e => e.Created >= dateBegin)
|
||||||
.Take(take)
|
.Take(take)
|
||||||
.ToArrayAsync(token);
|
.ToArrayAsync(token);
|
||||||
var dtos = entities
|
var dtos = entities
|
||||||
@ -81,8 +80,8 @@ namespace DD.Persistence.Repository.Repositories
|
|||||||
.GroupBy(e => 1)
|
.GroupBy(e => 1)
|
||||||
.Select(group => new
|
.Select(group => new
|
||||||
{
|
{
|
||||||
Min = group.Min(e => e.Timestamp),
|
Min = group.Min(e => e.Created),
|
||||||
Max = group.Max(e => e.Timestamp),
|
Max = group.Max(e => e.Created),
|
||||||
});
|
});
|
||||||
var values = await query.FirstOrDefaultAsync(token);
|
var values = await query.FirstOrDefaultAsync(token);
|
||||||
var result = new DatesRangeDto()
|
var result = new DatesRangeDto()
|
||||||
@ -114,7 +113,7 @@ namespace DD.Persistence.Repository.Repositories
|
|||||||
Key = setpointKey,
|
Key = setpointKey,
|
||||||
Value = newValue,
|
Value = newValue,
|
||||||
IdUser = idUser,
|
IdUser = idUser,
|
||||||
Timestamp = DateTimeOffset.UtcNow.ToUniversalTime()
|
Created = DateTimeOffset.UtcNow
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.Set<Setpoint>().AddAsync(entity, token);
|
await db.Set<Setpoint>().AddAsync(entity, token);
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
using DD.Persistence.Database.Entity;
|
|
||||||
using DD.Persistence.Extensions;
|
|
||||||
using DD.Persistence.Models;
|
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using DD.Persistence.Models.Requests;
|
|
||||||
using DD.Persistence.Repositories;
|
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using DD.Persistence.Database.Entity;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using DD.Persistence.Models.Requests;
|
||||||
|
using DD.Persistence.Repositories;
|
||||||
|
using UuidExtensions;
|
||||||
|
|
||||||
namespace DD.Persistence.Repository.Repositories
|
namespace DD.Persistence.Repository.Repositories
|
||||||
{
|
{
|
||||||
public class TechMessagesRepository : ITechMessagesRepository
|
public class TechMessagesRepository : ITechMessagesRepository
|
||||||
{
|
{
|
||||||
private readonly IDataSourceSystemRepository sourceSystemRepository;
|
private readonly IDataSourceSystemRepository sourceSystemRepository;
|
||||||
private DbContext db;
|
private DbContext db;
|
||||||
|
@ -0,0 +1,103 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using DD.Persistence.Database.Model;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Repository.Repositories;
|
||||||
|
|
||||||
|
public class TimeSeriesDataCachedRepository<TEntity, TDto> : TimeSeriesDataRepository<TEntity, TDto>
|
||||||
|
where TEntity : class, ITimestampedData, new()
|
||||||
|
where TDto : class, ITimeSeriesAbstractDto, new()
|
||||||
|
{
|
||||||
|
public static TDto? FirstByDate { get; private set; }
|
||||||
|
public static CyclicArray<TDto> LastData { get; } = new CyclicArray<TDto>(CacheItemsCount);
|
||||||
|
|
||||||
|
private const int CacheItemsCount = 3600;
|
||||||
|
|
||||||
|
public TimeSeriesDataCachedRepository(DbContext db) : base(db)
|
||||||
|
{
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var firstDateItem = await base.GetFirstAsync(CancellationToken.None);
|
||||||
|
if (firstDateItem == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FirstByDate = firstDateItem;
|
||||||
|
|
||||||
|
var dtos = await base.GetLastAsync(CacheItemsCount, CancellationToken.None);
|
||||||
|
dtos = dtos.OrderBy(d => d.Date);
|
||||||
|
LastData.AddRange(dtos);
|
||||||
|
}).Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset dateBegin, CancellationToken token)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (LastData.Count == 0 || LastData[0].Date > dateBegin)
|
||||||
|
{
|
||||||
|
var dtos = await base.GetGtDate(dateBegin, token);
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = LastData
|
||||||
|
.Where(i => i.Date >= dateBegin);
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
|
{
|
||||||
|
var result = await base.AddRange(dtos, token);
|
||||||
|
if (result > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
dtos = dtos.OrderBy(x => x.Date);
|
||||||
|
|
||||||
|
FirstByDate = dtos.First();
|
||||||
|
LastData.AddRange(dtos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<DatesRangeDto?> GetDatesRange(CancellationToken token)
|
||||||
|
{
|
||||||
|
if (FirstByDate == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return await Task.Run(() =>
|
||||||
|
{
|
||||||
|
return new DatesRangeDto
|
||||||
|
{
|
||||||
|
From = FirstByDate.Date,
|
||||||
|
To = LastData[^1].Date
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<IEnumerable<TDto>> GetResampledData(
|
||||||
|
DateTimeOffset dateBegin,
|
||||||
|
double intervalSec = 600d,
|
||||||
|
int approxPointsCount = 1024,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var dtos = LastData.Where(i => i.Date >= dateBegin);
|
||||||
|
if (LastData.Count == 0 || LastData[0].Date > dateBegin)
|
||||||
|
{
|
||||||
|
dtos = await base.GetGtDate(dateBegin, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dateEnd = dateBegin.AddSeconds(intervalSec);
|
||||||
|
dtos = dtos
|
||||||
|
.Where(i => i.Date <= dateEnd);
|
||||||
|
|
||||||
|
var ratio = dtos.Count() / approxPointsCount;
|
||||||
|
if (ratio > 1)
|
||||||
|
dtos = dtos
|
||||||
|
.Where((_, index) => index % ratio == 0);
|
||||||
|
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
|||||||
|
using Mapster;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using DD.Persistence.Database.Model;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using DD.Persistence.Repositories;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Repository.Repositories;
|
||||||
|
public class TimeSeriesDataRepository<TEntity, TDto> : ITimeSeriesDataRepository<TDto>
|
||||||
|
where TEntity : class, ITimestampedData, new()
|
||||||
|
where TDto : class, ITimeSeriesAbstractDto, new()
|
||||||
|
{
|
||||||
|
private readonly DbContext db;
|
||||||
|
|
||||||
|
public TimeSeriesDataRepository(DbContext db)
|
||||||
|
{
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual IQueryable<TEntity> GetQueryReadOnly() => this.db.Set<TEntity>();
|
||||||
|
|
||||||
|
public virtual async Task<DatesRangeDto?> GetDatesRange(CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = GetQueryReadOnly();
|
||||||
|
var minDate = await query.MinAsync(o => o.Date, token);
|
||||||
|
var maxDate = await query.MaxAsync(o => o.Date, token);
|
||||||
|
|
||||||
|
return new DatesRangeDto
|
||||||
|
{
|
||||||
|
From = minDate,
|
||||||
|
To = maxDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset date, CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = this.db.Set<TEntity>().Where(e => e.Date > date);
|
||||||
|
var entities = await query.ToArrayAsync(token);
|
||||||
|
|
||||||
|
var dtos = entities.Select(e => e.Adapt<TDto>());
|
||||||
|
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async Task<int> AddRange(IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
|
{
|
||||||
|
var entities = dtos.Select(d => d.Adapt<TEntity>());
|
||||||
|
|
||||||
|
await db.Set<TEntity>().AddRangeAsync(entities, token);
|
||||||
|
var result = await db.SaveChangesAsync(token);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<IEnumerable<TDto>> GetLastAsync(int takeCount, CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = GetQueryReadOnly()
|
||||||
|
.OrderByDescending(e => e.Date)
|
||||||
|
.Take(takeCount);
|
||||||
|
|
||||||
|
var entities = await query.ToArrayAsync(token);
|
||||||
|
var dtos = entities.Select(e => e.Adapt<TDto>());
|
||||||
|
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<TDto?> GetFirstAsync(CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = GetQueryReadOnly()
|
||||||
|
.OrderBy(e => e.Date);
|
||||||
|
|
||||||
|
var entity = await query.FirstOrDefaultAsync(token);
|
||||||
|
|
||||||
|
if (entity == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var dto = entity.Adapt<TDto>();
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async virtual Task<IEnumerable<TDto>> GetResampledData(
|
||||||
|
DateTimeOffset dateBegin,
|
||||||
|
double intervalSec = 600d,
|
||||||
|
int approxPointsCount = 1024,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var dtos = await GetGtDate(dateBegin, token);
|
||||||
|
|
||||||
|
var dateEnd = dateBegin.AddSeconds(intervalSec);
|
||||||
|
dtos = dtos
|
||||||
|
.Where(i => i.Date <= dateEnd);
|
||||||
|
|
||||||
|
var ratio = dtos.Count() / approxPointsCount;
|
||||||
|
if (ratio > 1)
|
||||||
|
dtos = dtos
|
||||||
|
.Where((_, index) => index % ratio == 0);
|
||||||
|
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using DD.Persistence.Database.Entity;
|
||||||
|
using DD.Persistence.Models;
|
||||||
|
using DD.Persistence.Repositories;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Repository.Repositories;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Репозиторий для хранения разных наборов данных временных рядов.
|
||||||
|
/// idDiscriminator - идентифицирует конкретный набор данных, прим.: циклы измерения АСИБР, или отчет о DrillTest.
|
||||||
|
/// idDiscriminator формируют клиенты и только им известно что они обозначают.
|
||||||
|
/// Так как данные приходят редко, то их прореживания для построения графиков не предусмотрено.
|
||||||
|
/// </summary>
|
||||||
|
public class TimestampedSetRepository : ITimestampedSetRepository
|
||||||
|
{
|
||||||
|
private readonly DbContext db;
|
||||||
|
|
||||||
|
public TimestampedSetRepository(DbContext db)
|
||||||
|
{
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> AddRange(Guid idDiscriminator, IEnumerable<TimestampedSetDto> sets, CancellationToken token)
|
||||||
|
{
|
||||||
|
var entities = sets.Select(set => new TimestampedSet(idDiscriminator, set.Timestamp.ToUniversalTime(), set.Set));
|
||||||
|
var dbSet = db.Set<TimestampedSet>();
|
||||||
|
dbSet.AddRange(entities);
|
||||||
|
return db.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TimestampedSetDto>> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
|
||||||
|
{
|
||||||
|
var dbSet = db.Set<TimestampedSet>();
|
||||||
|
var query = dbSet.Where(entity => entity.IdDiscriminator == idDiscriminator);
|
||||||
|
|
||||||
|
if (geTimestamp.HasValue)
|
||||||
|
query = ApplyGeTimestamp(query, geTimestamp.Value);
|
||||||
|
|
||||||
|
query = query
|
||||||
|
.OrderBy(item => item.Timestamp)
|
||||||
|
.Skip(skip)
|
||||||
|
.Take(take);
|
||||||
|
|
||||||
|
var data = await Materialize(query, token);
|
||||||
|
|
||||||
|
if (columnNames is not null && columnNames.Any())
|
||||||
|
data = ReduceSetColumnsByNames(data, columnNames);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TimestampedSetDto>> GetLast(Guid idDiscriminator, IEnumerable<string>? columnNames, int take, CancellationToken token)
|
||||||
|
{
|
||||||
|
var dbSet = db.Set<TimestampedSet>();
|
||||||
|
var query = dbSet.Where(entity => entity.IdDiscriminator == idDiscriminator);
|
||||||
|
|
||||||
|
query = query.OrderByDescending(entity => entity.Timestamp)
|
||||||
|
.Take(take)
|
||||||
|
.OrderBy(entity => entity.Timestamp);
|
||||||
|
|
||||||
|
var data = await Materialize(query, token);
|
||||||
|
|
||||||
|
if (columnNames is not null && columnNames.Any())
|
||||||
|
data = ReduceSetColumnsByNames(data, columnNames);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> Count(Guid idDiscriminator, CancellationToken token)
|
||||||
|
{
|
||||||
|
var dbSet = db.Set<TimestampedSet>();
|
||||||
|
var query = dbSet.Where(entity => entity.IdDiscriminator == idDiscriminator);
|
||||||
|
return query.CountAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token)
|
||||||
|
{
|
||||||
|
var query = db.Set<TimestampedSet>()
|
||||||
|
.GroupBy(entity => entity.IdDiscriminator)
|
||||||
|
.Select(group => new
|
||||||
|
{
|
||||||
|
Min = group.Min(entity => entity.Timestamp),
|
||||||
|
Max = group.Max(entity => entity.Timestamp),
|
||||||
|
});
|
||||||
|
|
||||||
|
var item = await query.FirstOrDefaultAsync(token);
|
||||||
|
if (item is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new DatesRangeDto
|
||||||
|
{
|
||||||
|
From = item.Min,
|
||||||
|
To = item.Max,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<IEnumerable<TimestampedSetDto>> Materialize(IQueryable<TimestampedSet> query, CancellationToken token)
|
||||||
|
{
|
||||||
|
var dtoQuery = query.Select(entity => new TimestampedSetDto(entity.Timestamp, entity.Set));
|
||||||
|
var dtos = await dtoQuery.ToArrayAsync(token);
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IQueryable<TimestampedSet> ApplyGeTimestamp(IQueryable<TimestampedSet> query, DateTimeOffset geTimestamp)
|
||||||
|
{
|
||||||
|
var geTimestampUtc = geTimestamp.ToUniversalTime();
|
||||||
|
return query.Where(entity => entity.Timestamp >= geTimestampUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<TimestampedSetDto> ReduceSetColumnsByNames(IEnumerable<TimestampedSetDto> query, IEnumerable<string> columnNames)
|
||||||
|
{
|
||||||
|
var newQuery = query
|
||||||
|
.Select(entity => new TimestampedSetDto(
|
||||||
|
entity.Timestamp,
|
||||||
|
entity.Set
|
||||||
|
.Where(prop => columnNames.Contains(prop.Key))
|
||||||
|
.ToDictionary(prop => prop.Key, prop => prop.Value)
|
||||||
|
));
|
||||||
|
return newQuery;
|
||||||
|
}
|
||||||
|
}
|
@ -1,179 +0,0 @@
|
|||||||
using DD.Persistence.Database.Entity;
|
|
||||||
using DD.Persistence.Models;
|
|
||||||
using DD.Persistence.Models.Common;
|
|
||||||
using DD.Persistence.Repositories;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Repository.Repositories;
|
|
||||||
public class TimestampedValuesRepository : ITimestampedValuesRepository
|
|
||||||
{
|
|
||||||
private readonly DbContext db;
|
|
||||||
|
|
||||||
public TimestampedValuesRepository(DbContext db)
|
|
||||||
{
|
|
||||||
this.db = db;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual IQueryable<TimestampedValues> GetQueryReadOnly() => this.db.Set<TimestampedValues>();
|
|
||||||
|
|
||||||
public async virtual Task<int> AddRange(Guid discriminatorId, IEnumerable<TimestampedValuesDto> dtos, CancellationToken token)
|
|
||||||
{
|
|
||||||
var timestampedValuesEntities = dtos.Select(dto => new TimestampedValues()
|
|
||||||
{
|
|
||||||
DiscriminatorId = discriminatorId,
|
|
||||||
Timestamp = dto.Timestamp.ToUniversalTime(),
|
|
||||||
Values = dto.Values.Values.ToArray()
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.Set<TimestampedValues>().AddRangeAsync(timestampedValuesEntities, token);
|
|
||||||
|
|
||||||
var result = await db.SaveChangesAsync(token);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async virtual Task<IDictionary<Guid, IEnumerable<(DateTimeOffset Timestamp, object[] Values)>>> Get(IEnumerable<Guid> discriminatorIds,
|
|
||||||
DateTimeOffset? timestampBegin,
|
|
||||||
IEnumerable<string>? columnNames,
|
|
||||||
int skip,
|
|
||||||
int take,
|
|
||||||
CancellationToken token)
|
|
||||||
{
|
|
||||||
var query = GetQueryReadOnly()
|
|
||||||
.Where(entity => discriminatorIds.Contains(entity.DiscriminatorId));
|
|
||||||
|
|
||||||
// Фильтрация по дате
|
|
||||||
if (timestampBegin.HasValue)
|
|
||||||
{
|
|
||||||
query = ApplyGeTimestamp(query, timestampBegin.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Группировка отсортированных значений по 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.ToDictionary(k => k.Key, v => v.Value.Select(e => (
|
|
||||||
e.Timestamp,
|
|
||||||
e.Values
|
|
||||||
)));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async virtual Task<IEnumerable<(DateTimeOffset Timestamp, object[] Values)>> 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 => (
|
|
||||||
e.Timestamp,
|
|
||||||
e.Values
|
|
||||||
));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async virtual Task<IEnumerable<(DateTimeOffset Timestamp, object[] Values)>> 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 => (
|
|
||||||
e.Timestamp,
|
|
||||||
e.Values
|
|
||||||
));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToDo: прореживание должно осуществляться до материализации
|
|
||||||
public async virtual Task<IEnumerable<(DateTimeOffset Timestamp, object[] Values)>> GetResampledData(
|
|
||||||
Guid discriminatorId,
|
|
||||||
DateTimeOffset dateBegin,
|
|
||||||
double intervalSec = 600d,
|
|
||||||
int approxPointsCount = 1024,
|
|
||||||
CancellationToken token = default)
|
|
||||||
{
|
|
||||||
var result = await GetGtDate(discriminatorId, dateBegin, token);
|
|
||||||
|
|
||||||
var dateEnd = dateBegin.AddSeconds(intervalSec);
|
|
||||||
result = result
|
|
||||||
.Where(i => i.Item1 <= dateEnd);
|
|
||||||
|
|
||||||
var ratio = result.Count() / approxPointsCount;
|
|
||||||
if (ratio > 1)
|
|
||||||
result = result
|
|
||||||
.Where((_, index) => index % ratio == 0);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async virtual Task<IEnumerable<(DateTimeOffset Timestamp, object[] Values)>> 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 => (
|
|
||||||
e.Timestamp,
|
|
||||||
e.Values
|
|
||||||
));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async virtual Task<DatesRangeDto?> GetDatesRange(Guid discriminatorId, CancellationToken token)
|
|
||||||
{
|
|
||||||
var query = GetQueryReadOnly()
|
|
||||||
.GroupBy(entity => entity.DiscriminatorId)
|
|
||||||
.Select(group => new
|
|
||||||
{
|
|
||||||
Min = group.Min(entity => entity.Timestamp),
|
|
||||||
Max = group.Max(entity => entity.Timestamp),
|
|
||||||
});
|
|
||||||
|
|
||||||
var item = await query.FirstOrDefaultAsync(token);
|
|
||||||
if (item is null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var dto = new DatesRangeDto
|
|
||||||
{
|
|
||||||
From = item.Min,
|
|
||||||
To = item.Max,
|
|
||||||
};
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual Task<int> Count(Guid discriminatorId, CancellationToken token)
|
|
||||||
{
|
|
||||||
var dbSet = db.Set<TimestampedValues>();
|
|
||||||
var query = dbSet.Where(entity => entity.DiscriminatorId == discriminatorId);
|
|
||||||
|
|
||||||
return query.CountAsync(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Применить фильтр по дате
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="query"></param>
|
|
||||||
/// <param name="timestampBegin"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private IQueryable<TimestampedValues> ApplyGeTimestamp(IQueryable<TimestampedValues> query, DateTimeOffset timestampBegin)
|
|
||||||
{
|
|
||||||
var geTimestampUtc = timestampBegin.ToUniversalTime();
|
|
||||||
|
|
||||||
var result = query
|
|
||||||
.Where(entity => entity.Timestamp >= geTimestampUtc);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
using DD.Persistence.Models;
|
|
||||||
using DD.Persistence.Repository.Repositories;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Repository.RepositoriesCached;
|
|
||||||
public class DataSchemeCachedRepository : DataSchemeRepository
|
|
||||||
{
|
|
||||||
private readonly IMemoryCache memoryCache;
|
|
||||||
|
|
||||||
public DataSchemeCachedRepository(DbContext db, IMemoryCache memoryCache) : base(db)
|
|
||||||
{
|
|
||||||
this.memoryCache = memoryCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task Add(DataSchemeDto dataSourceSystemDto, CancellationToken token)
|
|
||||||
{
|
|
||||||
await base.Add(dataSourceSystemDto, token);
|
|
||||||
|
|
||||||
memoryCache.Set(dataSourceSystemDto.DiscriminatorId, dataSourceSystemDto);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<DataSchemeDto?> Get(Guid discriminatorId, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = memoryCache.Get<DataSchemeDto>(discriminatorId)
|
|
||||||
?? await base.Get(discriminatorId, token);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
//using DD.Persistence.Models;
|
|
||||||
//using DD.Persistence.Models.Common;
|
|
||||||
//using DD.Persistence.Repositories;
|
|
||||||
//using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
//namespace DD.Persistence.Repository.Repositories;
|
|
||||||
|
|
||||||
//public class TimestampedValuesCachedRepository : TimestampedValuesRepository
|
|
||||||
//{
|
|
||||||
// public static TimestampedValuesDto? FirstByDate { get; private set; }
|
|
||||||
// public static CyclicArray<TimestampedValuesDto> LastData { get; } = new CyclicArray<TimestampedValuesDto>(CacheItemsCount);
|
|
||||||
|
|
||||||
// private const int CacheItemsCount = 3600;
|
|
||||||
|
|
||||||
// public TimestampedValuesCachedRepository(DbContext db, IDataSourceSystemRepository<ValuesIdentityDto> relatedDataRepository) : base(db, relatedDataRepository)
|
|
||||||
// {
|
|
||||||
// //Task.Run(async () =>
|
|
||||||
// //{
|
|
||||||
// // var firstDateItem = await base.GetFirst(CancellationToken.None);
|
|
||||||
// // if (firstDateItem == null)
|
|
||||||
// // {
|
|
||||||
// // return;
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // FirstByDate = firstDateItem;
|
|
||||||
|
|
||||||
// // var dtos = await base.GetLast(CacheItemsCount, CancellationToken.None);
|
|
||||||
// // dtos = dtos.OrderBy(d => d.Timestamp);
|
|
||||||
// // LastData.AddRange(dtos);
|
|
||||||
// //}).Wait();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override async Task<IEnumerable<TimestampedValuesDto>> GetGtDate(Guid discriminatorId, DateTimeOffset dateBegin, CancellationToken token)
|
|
||||||
// {
|
|
||||||
|
|
||||||
// if (LastData.Count == 0 || LastData[0].Timestamp > dateBegin)
|
|
||||||
// {
|
|
||||||
// var dtos = await base.GetGtDate(discriminatorId, dateBegin, token);
|
|
||||||
// return dtos;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var items = LastData
|
|
||||||
// .Where(i => i.Timestamp >= dateBegin);
|
|
||||||
|
|
||||||
// return items;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override async Task<int> AddRange(Guid discriminatorId, IEnumerable<TimestampedValuesDto> dtos, CancellationToken token)
|
|
||||||
// {
|
|
||||||
// var result = await base.AddRange(discriminatorId, dtos, token);
|
|
||||||
// if (result > 0)
|
|
||||||
// {
|
|
||||||
|
|
||||||
// dtos = dtos.OrderBy(x => x.Timestamp);
|
|
||||||
|
|
||||||
// FirstByDate = dtos.First();
|
|
||||||
// LastData.AddRange(dtos);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override async Task<DatesRangeDto?> GetDatesRange(Guid discriminatorId, CancellationToken token)
|
|
||||||
// {
|
|
||||||
// if (FirstByDate == null)
|
|
||||||
// return null;
|
|
||||||
|
|
||||||
// return await Task.Run(() =>
|
|
||||||
// {
|
|
||||||
// return new DatesRangeDto
|
|
||||||
// {
|
|
||||||
// From = FirstByDate.Timestamp,
|
|
||||||
// To = LastData[^1].Timestamp
|
|
||||||
// };
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override async Task<IEnumerable<TimestampedValuesDto>> GetResampledData(
|
|
||||||
// Guid discriminatorId,
|
|
||||||
// DateTimeOffset dateBegin,
|
|
||||||
// double intervalSec = 600d,
|
|
||||||
// int approxPointsCount = 1024,
|
|
||||||
// CancellationToken token = default)
|
|
||||||
// {
|
|
||||||
// var dtos = LastData.Where(i => i.Timestamp >= dateBegin);
|
|
||||||
// if (LastData.Count == 0 || LastData[0].Timestamp > dateBegin)
|
|
||||||
// {
|
|
||||||
// dtos = await base.GetGtDate(discriminatorId, dateBegin, token);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var dateEnd = dateBegin.AddSeconds(intervalSec);
|
|
||||||
// dtos = dtos
|
|
||||||
// .Where(i => i.Timestamp <= dateEnd);
|
|
||||||
|
|
||||||
// var ratio = dtos.Count() / approxPointsCount;
|
|
||||||
// if (ratio > 1)
|
|
||||||
// dtos = dtos
|
|
||||||
// .Where((_, index) => index % ratio == 0);
|
|
||||||
|
|
||||||
// return dtos;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
|
||||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
|
||||||
<PackageReference Include="xunit" Version="2.9.2" />
|
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\DD.Persistence.Database\DD.Persistence.Database.csproj" />
|
|
||||||
<ProjectReference Include="..\DD.Persistence\DD.Persistence.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Using Include="Xunit" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,34 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Test;
|
|
||||||
public class TableAttributeShould
|
|
||||||
{
|
|
||||||
private const string Separator = "_";
|
|
||||||
private const string TargetAssembly = "DD.Persistence.Database";
|
|
||||||
private const string TargetNamespace = "DD.Persistence.Database.Entity";
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Test()
|
|
||||||
{
|
|
||||||
Assembly assembly = Assembly.Load(TargetAssembly);
|
|
||||||
var typesInNamespace = assembly.GetTypes()
|
|
||||||
.Where(t => t.IsClass && t.Namespace == TargetNamespace)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (var type in typesInNamespace)
|
|
||||||
{
|
|
||||||
var tableAttribute = type.GetCustomAttribute<TableAttribute>();
|
|
||||||
Assert.NotNull(tableAttribute);
|
|
||||||
|
|
||||||
var partsOfClassName = Regex
|
|
||||||
.Split(type.Name, @"(?=[A-Z])")
|
|
||||||
.Where(s => s != string.Empty)
|
|
||||||
.Select(s => s.ToLower(CultureInfo.InvariantCulture));
|
|
||||||
var expectedClassName = string.Join(Separator, partsOfClassName);
|
|
||||||
Assert.Equal(expectedClassName, tableAttribute.Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
using DD.Persistence.Models;
|
|
||||||
using DD.Persistence.Repositories;
|
|
||||||
using DD.Persistence.Services;
|
|
||||||
using NSubstitute;
|
|
||||||
|
|
||||||
namespace DD.Persistence.Repository.Test;
|
|
||||||
public class TimestampedValuesServiceShould
|
|
||||||
{
|
|
||||||
private readonly ITimestampedValuesRepository timestampedValuesRepository = Substitute.For<ITimestampedValuesRepository>();
|
|
||||||
private readonly IDataSchemeRepository dataSchemeRepository = Substitute.For<IDataSchemeRepository>();
|
|
||||||
private TimestampedValuesService timestampedValuesService;
|
|
||||||
|
|
||||||
public TimestampedValuesServiceShould()
|
|
||||||
{
|
|
||||||
timestampedValuesService = new TimestampedValuesService(timestampedValuesRepository, dataSchemeRepository);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task TestServiceEfficiency()
|
|
||||||
{
|
|
||||||
var discriminatorIds = new[] { Guid.NewGuid(), Guid.NewGuid() };
|
|
||||||
const int count = 10;
|
|
||||||
var dtos = Generate(count, DateTimeOffset.UtcNow);
|
|
||||||
var addRangeResult = await timestampedValuesService
|
|
||||||
.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" };
|
|
||||||
var geTimestamp = DateTimeOffset.UtcNow
|
|
||||||
.AddHours(-1)
|
|
||||||
.ToUniversalTime();
|
|
||||||
var getResult = await timestampedValuesService
|
|
||||||
.Get(discriminatorIds, geTimestamp, columnNames, 0, count, CancellationToken.None);
|
|
||||||
Assert.NotNull(getResult);
|
|
||||||
Assert.Empty(getResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<TimestampedValuesDto> Generate(int countToCreate, DateTimeOffset from)
|
|
||||||
{
|
|
||||||
var result = new List<TimestampedValuesDto>();
|
|
||||||
for (int i = 0; i < countToCreate; i++)
|
|
||||||
{
|
|
||||||
var values = new Dictionary<string, object>()
|
|
||||||
{
|
|
||||||
{ "A", i },
|
|
||||||
{ "B", i * 1.1 },
|
|
||||||
{ "C", $"Any{i}" },
|
|
||||||
{ "D", DateTimeOffset.Now },
|
|
||||||
};
|
|
||||||
|
|
||||||
yield return new TimestampedValuesDto()
|
|
||||||
{
|
|
||||||
Timestamp = from.AddSeconds(i),
|
|
||||||
Values = values
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -28,13 +28,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt
|
|||||||
Directory.Build.props = Directory.Build.props
|
Directory.Build.props = Directory.Build.props
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
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
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -81,10 +74,6 @@ Global
|
|||||||
{08B03623-A1C9-482F-B60E-09F293E04999}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{08B03623-A1C9-482F-B60E-09F293E04999}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{08B03623-A1C9-482F-B60E-09F293E04999}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{08B03623-A1C9-482F-B60E-09F293E04999}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{08B03623-A1C9-482F-B60E-09F293E04999}.Release|Any CPU.Build.0 = Release|Any CPU
|
{08B03623-A1C9-482F-B60E-09F293E04999}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{B8C774E6-6B75-41AC-B3CF-10BD3623B2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{B8C774E6-6B75-41AC-B3CF-10BD3623B2FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{B8C774E6-6B75-41AC-B3CF-10BD3623B2FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{B8C774E6-6B75-41AC-B3CF-10BD3623B2FA}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -7,7 +7,7 @@ namespace DD.Persistence.API;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Интерфейс для работы с API журнала изменений
|
/// Интерфейс для работы с API журнала изменений
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IChangeLogApi : ISyncWithDiscriminatorApi<ChangeLogValuesDto>
|
public interface IChangeLogApi : ISyncWithDiscriminatorApi<DataWithWellDepthAndSectionDto>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Импорт с заменой: удаление старых строк и добавление новых
|
/// Импорт с заменой: удаление старых строк и добавление новых
|
||||||
@ -16,26 +16,28 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi<ChangeLogValuesDto>
|
|||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> ClearAndAddRange(Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token);
|
Task<IActionResult> ClearAndAddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение данных на текущую дату (с пагинацией)
|
/// Получение данных на текущую дату (с пагинацией)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idDiscriminator"></param>
|
/// <param name="idDiscriminator"></param>
|
||||||
|
/// <param name="filterRequest">параметры запроса фильтрации</param>
|
||||||
/// <param name="paginationRequest">параметры запроса пагинации</param>
|
/// <param name="paginationRequest">параметры запроса пагинации</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> GetCurrent(Guid idDiscriminator, PaginationRequest paginationRequest, CancellationToken token);
|
Task<IActionResult> GetCurrent(Guid idDiscriminator, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение данных на определенную дату (с пагинацией)
|
/// Получение данных на определенную дату (с пагинацией)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idDiscriminator"></param>
|
/// <param name="idDiscriminator"></param>
|
||||||
/// <param name="moment"></param>
|
/// <param name="moment"></param>
|
||||||
|
/// <param name="filterRequest">параметры запроса фильтрации</param>
|
||||||
/// <param name="paginationRequest">параметры запроса пагинации</param>
|
/// <param name="paginationRequest">параметры запроса пагинации</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> GetByDate(Guid idDiscriminator, DateTimeOffset moment, PaginationRequest paginationRequest, CancellationToken token);
|
Task<IActionResult> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение исторических данных за определенный период времени
|
/// Получение исторических данных за определенный период времени
|
||||||
@ -54,7 +56,7 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi<ChangeLogValuesDto>
|
|||||||
/// <param name="dto"></param>
|
/// <param name="dto"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> Add(Guid idDiscriminator, ChangeLogValuesDto dto, CancellationToken token);
|
Task<IActionResult> Add(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавить несколько записей
|
/// Добавить несколько записей
|
||||||
@ -63,7 +65,7 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi<ChangeLogValuesDto>
|
|||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> AddRange(Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token);
|
Task<IActionResult> AddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обновить одну запись
|
/// Обновить одну запись
|
||||||
@ -71,7 +73,7 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi<ChangeLogValuesDto>
|
|||||||
/// <param name="dto"></param>
|
/// <param name="dto"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> Update(ChangeLogValuesDto dto, CancellationToken token);
|
Task<IActionResult> Update(DataWithWellDepthAndSectionDto dto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обновить несколько записей
|
/// Обновить несколько записей
|
||||||
@ -79,7 +81,7 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi<ChangeLogValuesDto>
|
|||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> UpdateRange(IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token);
|
Task<IActionResult> UpdateRange(IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Удалить одну запись
|
/// Удалить одну запись
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using DD.Persistence.Models.Common;
|
using DD.Persistence.Models;
|
||||||
|
|
||||||
namespace DD.Persistence.API;
|
namespace DD.Persistence.API;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using DD.Persistence.Models.Common;
|
using DD.Persistence.Models;
|
||||||
|
|
||||||
namespace DD.Persistence.API;
|
namespace DD.Persistence.API;
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user