featute/ChangeLog #6

Merged
on.nemtina merged 25 commits from featute/ChangeLog into master 2024-12-09 17:44:48 +05:00
11 changed files with 93 additions and 241 deletions
Showing only changes of commit 6447b5e94f - Show all commits

View File

@ -27,7 +27,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
CancellationToken token) CancellationToken token)
{ {
var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
Review

Тут Да же проблема что и с сообщениями. Id системы, которая нам эти данные отправила, сюда не очень подходит

Тут Да же проблема что и с сообщениями. Id системы, которая нам эти данные отправила, сюда не очень подходит
Review

Решили пока оставить, как есть

Решили пока оставить, как есть
var result = await repository.InsertRange(userId, idDiscriminator, [dto], token); var result = await repository.AddRange(userId, idDiscriminator, [dto], token);
return CreatedAtAction(nameof(Add), result); return CreatedAtAction(nameof(Add), result);
} }
@ -40,7 +40,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
CancellationToken token = default) CancellationToken token = default)
{ {
var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var result = await repository.InsertRange(userId, idDiscriminator, dtos, token); var result = await repository.AddRange(userId, idDiscriminator, dtos, token);
return CreatedAtAction(nameof(AddRange), result); return CreatedAtAction(nameof(AddRange), result);
} }
@ -67,25 +67,24 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
[HttpPost("replace")] [HttpPost("replace")]
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
public async Task<IActionResult> ClearAndInsertRange( public async Task<IActionResult> ClearAndAddRange(
Guid idDiscriminator, Guid idDiscriminator,
IEnumerable<DataWithWellDepthAndSectionDto> dtos, IEnumerable<DataWithWellDepthAndSectionDto> dtos,
CancellationToken token = default) CancellationToken token = default)
{ {
var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var result = await repository.ClearAndInsertRange(userId, idDiscriminator, dtos, token); var result = await repository.ClearAndAddRange(userId, idDiscriminator, dtos, token);
return Ok(result); return Ok(result);
} }
[HttpPut] [HttpPut]
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
public async Task<IActionResult> Update( public async Task<IActionResult> Update(
Guid idDiscriminator,
DataWithWellDepthAndSectionDto dto, DataWithWellDepthAndSectionDto dto,
CancellationToken token = default) CancellationToken token = default)
{ {
var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var result = await repository.UpdateRange(userId, idDiscriminator, [dto], token); var result = await repository.UpdateRange(userId, [dto], token);
return Ok(result); return Ok(result);
} }
@ -93,12 +92,11 @@ 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(
Guid idDiscriminator,
IEnumerable<DataWithWellDepthAndSectionDto> dtos, IEnumerable<DataWithWellDepthAndSectionDto> dtos,
CancellationToken token = default) CancellationToken token = default)
{ {
var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var result = await repository.UpdateRange(userId, idDiscriminator, dtos, token); var result = await repository.UpdateRange(userId, dtos, token);
return Ok(result); return Ok(result);
} }
@ -107,11 +105,12 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
[ProducesResponseType(typeof(PaginationContainer<DataWithWellDepthAndSectionDto>), (int)HttpStatusCode.OK)] [ProducesResponseType(typeof(PaginationContainer<DataWithWellDepthAndSectionDto>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetCurrent( public async Task<IActionResult> GetCurrent(
Guid idDiscriminator, Guid idDiscriminator,
[FromQuery]SectionPartRequest request, [FromQuery]SectionPartRequest filterRequest,
[FromQuery] PaginationRequest paginationRequest,
CancellationToken token = default) CancellationToken token = default)
{ {
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, request, token); var result = await repository.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token);
return Ok(result); return Ok(result);
} }
@ -121,10 +120,11 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
public async Task<IActionResult> GetByDate( public async Task<IActionResult> GetByDate(
Guid idDiscriminator, Guid idDiscriminator,
DateTimeOffset moment, DateTimeOffset moment,
[FromQuery] SectionPartRequest request, [FromQuery] SectionPartRequest filterRequest,
[FromQuery] PaginationRequest paginationRequest,
CancellationToken token = default) CancellationToken token = default)
{ {
var result = await repository.GetByDate(idDiscriminator, moment, request, token); var result = await repository.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest, token);
return Ok(result); return Ok(result);
} }

View File

@ -18,17 +18,22 @@ public interface IChangeLogClient
/// <param name="dtos"></param> /// <param name="dtos"></param>
/// <returns></returns> /// <returns></returns>
[Post($"{BaseRoute}/replace")] [Post($"{BaseRoute}/replace")]
Task<IApiResponse<int>> ClearAndInsertRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos); Task<IApiResponse<int>> ClearAndAddRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos);
/// <summary> /// <summary>
/// Получение актуальных данных на определенную дату (с пагинацией) /// Получение актуальных данных на определенную дату (с пагинацией)
/// </summary> /// </summary>
/// <param name="idDiscriminator"></param> /// <param name="idDiscriminator"></param>
/// <param name="moment"></param> /// <param name="moment"></param>
/// <param name="request">параметры запроса</param> /// <param name="filterRequest">параметры запроса фильтрации</param>
/// <param name="paginationRequest">параметры запроса пагинации</param>
/// <returns></returns> /// <returns></returns>
[Get($"{BaseRoute}/moment")] [Get($"{BaseRoute}/moment")]
Task<IApiResponse<PaginationContainer<DataWithWellDepthAndSectionDto>>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, [Query] SectionPartRequest request); Task<IApiResponse<PaginationContainer<DataWithWellDepthAndSectionDto>>> GetByDate(
Guid idDiscriminator,
DateTimeOffset moment,
[Query] SectionPartRequest filterRequest,
[Query] PaginationRequest paginationRequest);
/// <summary> /// <summary>
/// Получение исторических данных за определенный период времени /// Получение исторических данных за определенный период времени

View File

@ -31,7 +31,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var dtos = Generate(2, DateTimeOffset.UtcNow); var dtos = Generate(2, DateTimeOffset.UtcNow);
// act // act
var result = await client.ClearAndInsertRange(idDiscriminator, dtos); var result = await client.ClearAndAddRange(idDiscriminator, dtos);
// assert // assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(HttpStatusCode.OK, result.StatusCode);
@ -51,7 +51,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var result = await client.Add(idDiscriminator, dto); var result = await client.Add(idDiscriminator, dto);
// assert // assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(HttpStatusCode.Created, result.StatusCode);
Assert.Equal(count, result.Content); Assert.Equal(count, result.Content);
} }
@ -67,7 +67,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var result = await client.AddRange(idDiscriminator, dtos); var result = await client.AddRange(idDiscriminator, dtos);
// assert // assert
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(HttpStatusCode.Created, result.StatusCode);
Assert.Equal(count, result.Content); Assert.Equal(count, result.Content);
} }
@ -79,7 +79,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var dtos = Generate(1, DateTimeOffset.UtcNow); var dtos = Generate(1, DateTimeOffset.UtcNow);
var dto = dtos.FirstOrDefault()!; var dto = dtos.FirstOrDefault()!;
var result = await client.Add(idDiscriminator, dto); var result = await client.Add(idDiscriminator, dto);
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(HttpStatusCode.Created, result.StatusCode);
var entity = dbContext.ChangeLog var entity = dbContext.ChangeLog
.Where(x => x.IdDiscriminator == idDiscriminator) .Where(x => x.IdDiscriminator == idDiscriminator)
@ -230,7 +230,13 @@ public class ChangeLogControllerTest : BaseIntegrationTest
var deletedCount = await client.DeleteRange(idsToDelete); var deletedCount = await client.DeleteRange(idsToDelete);
var request = new SectionPartRequest() var filterRequest = new SectionPartRequest()
{
DepthStart = 0,
DepthEnd = 1000,
};
var paginationRequest = new PaginationRequest()
{ {
Skip = 0, Skip = 0,
Take = 10, Take = 10,
@ -238,7 +244,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
}; };
var moment = DateTimeOffset.UtcNow.AddDays(16); var moment = DateTimeOffset.UtcNow.AddDays(16);
var result = await client.GetByDate(idDiscriminator, moment, request); var result = await client.GetByDate(idDiscriminator, moment, filterRequest, paginationRequest);
Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Equal(HttpStatusCode.OK, result.StatusCode);
Assert.NotNull(result.Content); Assert.NotNull(result.Content);
@ -256,16 +262,16 @@ public class ChangeLogControllerTest : BaseIntegrationTest
[InlineData(5, -15, -10, -16, -9, 5)] [InlineData(5, -15, -10, -16, -9, 5)]
public async Task GetChangeLogForInterval_returns_success( public async Task GetChangeLogForInterval_returns_success(
int insertedCount, int insertedCount,
int leftCreationFromCurrentDate, int daysBeforeNowChangeLog,
int rightCreationFromCurrentDate, int daysAfterNowChangeLog,
int leftPointFromCurrentDate, int daysBeforeNowFilter,
int rightPointFromCurrentDate, int daysAfterNowFilter,
int changeLogCount) int changeLogCount)
{ {
// arrange // arrange
//создаем записи //создаем записи
var count = insertedCount; var count = insertedCount;
var daysRange = (leftCreationFromCurrentDate, rightCreationFromCurrentDate); var daysRange = (daysBeforeNowChangeLog, daysAfterNowChangeLog);
var changeLogItems = CreateChangeLogItems(count, daysRange); var changeLogItems = CreateChangeLogItems(count, daysRange);
var idDiscriminator = changeLogItems.Item1; var idDiscriminator = changeLogItems.Item1;
var entities = changeLogItems.Item2; var entities = changeLogItems.Item2;
@ -278,8 +284,8 @@ public class ChangeLogControllerTest : BaseIntegrationTest
await client.UpdateRange(idDiscriminator, dtos); await client.UpdateRange(idDiscriminator, dtos);
//act //act
var dateBegin = DateTimeOffset.UtcNow.AddDays(leftPointFromCurrentDate); var dateBegin = DateTimeOffset.UtcNow.AddDays(daysBeforeNowFilter);
var dateEnd = DateTimeOffset.UtcNow.AddDays(rightPointFromCurrentDate); var dateEnd = DateTimeOffset.UtcNow.AddDays(daysAfterNowFilter);
var result = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd); var result = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd);
//assert //assert

View File

@ -15,11 +15,11 @@ public class ChangeLogRepository : IChangeLogRepository
this.db = db; this.db = db;
} }
public async Task<int> InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token) public async Task<int> AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
{ {
foreach (var dto in dtos) foreach (var dto in dtos)
{ {
var entity = CreateEntityFromDto(idUser, idDiscriminator, dto); var entity = CreateEntityFromDto(idAuthor, idDiscriminator, dto);
db.Set<ChangeLog>().Add(entity); db.Set<ChangeLog>().Add(entity);
Review

db.Set() хоть и не дорогой но не бесплатный:) Получать его для каждой dto как-то не оправданно.

db.Set<ChangeLog>() хоть и не дорогой но не бесплатный:) Получать его для каждой dto как-то не оправданно.
} }
@ -28,49 +28,49 @@ public class ChangeLogRepository : IChangeLogRepository
return result; return result;
} }
public async Task<int> MarkAsDeleted(Guid idUser, IEnumerable<Guid> ids, CancellationToken token) public async Task<int> MarkAsDeleted(Guid idEditor, IEnumerable<Guid> ids, CancellationToken token)
{ {
var query = db.Set<ChangeLog>().Where(s => ids.Contains(s.Id)); var query = db.Set<ChangeLog>().Where(s => ids.Contains(s.Id));
var entities = await query.ToArrayAsync(token); var entities = await query.ToArrayAsync(token);
Review

Стоит проверить, что количество записей совпадает с количеством ids. Если не совпадает - исключение

Стоит проверить, что количество записей совпадает с количеством ids. Если не совпадает - исключение
var result = await Clear(idUser, entities, token); var result = await Clear(idEditor, entities, token);
return result; return result;
} }
public async Task<int> MarkAsDeleted(Guid idUser, Guid idDiscriminator, CancellationToken token) public async Task<int> MarkAsDeleted(Guid idEditor, Guid idDiscriminator, CancellationToken token)
{ {
var query = db.Set<ChangeLog>() var query = db.Set<ChangeLog>()
.Where(s => s.IdDiscriminator == idDiscriminator) .Where(s => s.IdDiscriminator == idDiscriminator)
.Where(e => e.Obsolete == null); .Where(e => e.Obsolete == null);
var entities = await query.ToArrayAsync(token); var entities = await query.ToArrayAsync(token);
var result = await Clear(idUser, entities, token); var result = await Clear(idEditor, entities, token);
return result; return result;
} }
private async Task<int> Clear(Guid idUser, IEnumerable<ChangeLog> entities, CancellationToken token) private async Task<int> Clear(Guid idEditor, IEnumerable<ChangeLog> entities, CancellationToken token)

немного смущает название

немного смущает название
{ {
var updateTime = DateTimeOffset.UtcNow; var updateTime = DateTimeOffset.UtcNow;
foreach (var entity in entities) foreach (var entity in entities)

Думаю тут будет разумно проверить, что помечаемые записи еще не устарели. И если мы собираемся отредактировать устаревшее, то падаем в исключение.

Думаю тут будет разумно проверить, что помечаемые записи еще не устарели. И если мы собираемся отредактировать устаревшее, то падаем в исключение.
{ {
entity.Obsolete = updateTime; entity.Obsolete = updateTime;
entity.IdEditor = idUser; entity.IdEditor = idEditor;
} }
return await db.SaveChangesAsync(token); return await db.SaveChangesAsync(token);
} }
public async Task<int> ClearAndInsertRange(Guid idUser, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token) public async Task<int> ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token)
{ {
var result = 0; var result = 0;
using var transaction = await db.Database.BeginTransactionAsync(token); using var transaction = await db.Database.BeginTransactionAsync(token);
try try
Review

try-catch тут и дальше не нужен. Rollback ролбэк будет вызван финализатором транзакции, если не был вызван комит

try-catch тут и дальше не нужен. Rollback ролбэк будет вызван финализатором транзакции, если не был вызван комит
{ {
result += await MarkAsDeleted(idUser, idDiscriminator, token); result += await MarkAsDeleted(idAuthor, idDiscriminator, token);
result += await InsertRange(idUser, idDiscriminator, dtos, token); result += await AddRange(idAuthor, idDiscriminator, dtos, token);
await transaction.CommitAsync(token); await transaction.CommitAsync(token);
return result; return result;
@ -82,7 +82,7 @@ public class ChangeLogRepository : IChangeLogRepository
} }
} }
public async Task<int> UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> 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>();
@ -97,13 +97,18 @@ public class ChangeLogRepository : IChangeLogRepository
{ {
foreach (var dto in dtos) foreach (var dto in dtos)
{ {
var newEntity = CreateEntityFromDto(idUser, idDiscriminator, dto); var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id);
if(updatedEntity is null)
{
throw new ArgumentNullException($"Entity with id = {dto.Id} doesn't exist in Db", nameof(dto));

Не тот тип эксепшена.
Лучше использовать ArgumentException, а в middleware его перехватить и вернуть пользователю 400

Не тот тип эксепшена. Лучше использовать ArgumentException, а в middleware его перехватить и вернуть пользователю 400
}

try-catch тут и дальше не нужен. Rollback ролбэк будет вызван финализатором транзакции, если не был вызван комит

try-catch тут и дальше не нужен. Rollback ролбэк будет вызван финализатором транзакции, если не был вызван комит
var newEntity = CreateEntityFromDto(idEditor, updatedEntity.IdDiscriminator, dto);
dbSet.Add(newEntity); dbSet.Add(newEntity);
var updatedEntity = updatedEntities.GetValueOrDefault(dto.Id)!;
updatedEntity.IdNext = newEntity.Id; updatedEntity.IdNext = newEntity.Id;
updatedEntity.Obsolete = DateTimeOffset.UtcNow; updatedEntity.Obsolete = DateTimeOffset.UtcNow;
updatedEntity.IdEditor = idUser; updatedEntity.IdEditor = idEditor;
} }
result = await db.SaveChangesAsync(token); result = await db.SaveChangesAsync(token);
@ -121,11 +126,12 @@ public class ChangeLogRepository : IChangeLogRepository
public async Task<PaginationContainer<DataWithWellDepthAndSectionDto>> GetByDate( public async Task<PaginationContainer<DataWithWellDepthAndSectionDto>> GetByDate(
Guid idDiscriminator, Guid idDiscriminator,
DateTimeOffset momentUtc, DateTimeOffset momentUtc,
SectionPartRequest request, SectionPartRequest filterRequest,
PaginationRequest paginationRequest,
CancellationToken token) CancellationToken token)
{ {
var query = BuildQuery(idDiscriminator, momentUtc, request); var query = BuildQuery(idDiscriminator, momentUtc, filterRequest);
var result = await BuildPaginationContainer(query, request, token); var result = await BuildPaginationContainer(query, paginationRequest, token);
return result; return result;
} }
@ -173,7 +179,7 @@ public class ChangeLogRepository : IChangeLogRepository
private async Task<PaginationContainer<DataWithWellDepthAndSectionDto>> BuildPaginationContainer(IQueryable<ChangeLog> query, SectionPartRequest request, CancellationToken token) private async Task<PaginationContainer<DataWithWellDepthAndSectionDto>> BuildPaginationContainer(IQueryable<ChangeLog> query, PaginationRequest request, CancellationToken token)
{ {
var result = new PaginationContainer<DataWithWellDepthAndSectionDto> var result = new PaginationContainer<DataWithWellDepthAndSectionDto>
Review

result лучше собирать, когда для него уже есть все данные

result лучше собирать, когда для него уже есть все данные
{ {
@ -232,15 +238,15 @@ public class ChangeLogRepository : IChangeLogRepository
return datesOnly; return datesOnly;
} }
private ChangeLog CreateEntityFromDto(Guid idUser, Guid idDiscriminator, DataWithWellDepthAndSectionDto dto) private ChangeLog CreateEntityFromDto(Guid idAuthor, Guid idDiscriminator, DataWithWellDepthAndSectionDto dto)
{ {
var entity = new ChangeLog() var entity = new ChangeLog()
{ {
Id = default, Id = default,

Не все базы так поймут. Лучше для новых сущностей их генерировать самостоятельно (в идеале по седьмой версии).

Не все базы так поймут. Лучше для новых сущностей их генерировать самостоятельно (в идеале по [седьмой версии](https://steven-giesel.com/blogPost/ea42a518-4d8b-4e08-8f73-e542bdd3b983)).
Creation = DateTimeOffset.UtcNow, Creation = DateTimeOffset.UtcNow,
IdAuthor = idUser, IdAuthor = idAuthor,
IdDiscriminator = idDiscriminator, IdDiscriminator = idDiscriminator,
IdEditor = idUser, IdEditor = idAuthor,
Value = dto.Value, Value = dto.Value,
IdSection = dto.IdSection, IdSection = dto.IdSection,

View File

@ -16,26 +16,28 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi<DataWithWellDepthAndS
/// <param name="dtos"></param> /// <param name="dtos"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IActionResult> ClearAndInsertRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> 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="request">параметры запроса</param> /// <param name="filterRequest">параметры запроса фильтрации</param>
/// <param name="paginationRequest">параметры запроса пагинации</param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IActionResult> GetCurrent(Guid idDiscriminator, SectionPartRequest request, 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="request">параметры запроса</param> /// <param name="filterRequest">параметры запроса фильтрации</param>
/// <param name="paginationRequest">параметры запроса пагинации</param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IActionResult> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest request, CancellationToken token); Task<IActionResult> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token);
/// <summary> /// <summary>
/// Получение исторических данных за определенный период времени /// Получение исторических данных за определенный период времени
@ -68,20 +70,18 @@ public interface IChangeLogApi : ISyncWithDiscriminatorApi<DataWithWellDepthAndS
/// <summary> /// <summary>
/// Обновить одну запись /// Обновить одну запись
/// </summary> /// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dto"></param> /// <param name="dto"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IActionResult> Update(Guid idDiscriminator, DataWithWellDepthAndSectionDto dto, CancellationToken token); Task<IActionResult> Update(DataWithWellDepthAndSectionDto dto, CancellationToken token);
/// <summary> /// <summary>
/// Обновить несколько записей /// Обновить несколько записей
/// </summary> /// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dtos"></param> /// <param name="dtos"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IActionResult> UpdateRange(Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token); Task<IActionResult> UpdateRange(IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
/// <summary> /// <summary>
/// Удалить одну запись /// Удалить одну запись

View File

@ -7,7 +7,7 @@ namespace Persistence.API;
/// Интерфейс для API, предназначенного для работы с табличными данными /// Интерфейс для API, предназначенного для работы с табличными данными
public interface ITableDataApi<TDto, TRequest> public interface ITableDataApi<TDto, TRequest>
where TDto : class, new() where TDto : class, new()
where TRequest : Request where TRequest : PaginationRequest
{ {
/// <summary> /// <summary>
/// Получить страницу списка объектов /// Получить страницу списка объектов

View File

@ -4,7 +4,7 @@
/// Контейнер для поддержки постраничного просмотра таблиц /// Контейнер для поддержки постраничного просмотра таблиц
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public class Request public class PaginationRequest
{ {
/// <summary> /// <summary>
/// Кол-во записей пропущенных с начала таблицы в запросе от api /// Кол-во записей пропущенных с начала таблицы в запросе от api

View File

@ -3,7 +3,7 @@
/// <summary> /// <summary>
/// Запрос для фильтрации данных по секции и глубине /// Запрос для фильтрации данных по секции и глубине
/// </summary> /// </summary>
public class SectionPartRequest : Request public class SectionPartRequest

Возможно тут было бы проще без наследования

Возможно тут было бы проще без наследования
{ {
/// <summary> /// <summary>
/// Глубина забоя на дату начала интервала /// Глубина забоя на дату начала интервала

View File

@ -1,165 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Persistence.Models;
using System.Linq;
namespace Persistence.Repositories;
//public abstract class AbstractChangeLogRepository<TEntity, TChangeLogDto, TDto> : IChangeLogRepository<TDto, TChangeLogDto>
// where TDto : class, new()
// where TEntity : class, IChangeLogAbstract
// where TChangeLogDto : ChangeLogDto<TDto>
//{
// private readonly DbContext dbContext;
// protected AbstractChangeLogRepository(DbContext dbContext)
// {
// this.dbContext = dbContext;
// }
// public abstract TEntity Convert(TDto entity);
// public async Task<int> Clear(int idUser,CancellationToken token)
// {
// throw new NotImplementedException();
// //var updateTime = DateTimeOffset.UtcNow;
// ////todo
// //var query = BuildQuery(request);
// //query = query.Where(e => e.Obsolete == null);
// //var entitiesToDelete = await query.ToArrayAsync(token);
// //foreach (var entity in entitiesToDelete)
// //{
// // entity.IdState = IChangeLogAbstract.IdCleared;
// // entity.Obsolete = updateTime;
// // entity.IdEditor = idUser;
// //}
// //var result = await SaveChangesWithExceptionHandling(token);
// //return result;
// }
// public async Task<int> ClearAndInsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
// {
// var result = 0;
// using var transaction = await dbContext.Database.BeginTransactionAsync(token);
// try
// {
// result += await Clear(idUser, token);
// result += await InsertRangeWithoutTransaction(idUser, dtos, token);
// await transaction.CommitAsync(token);
// return result;
// }
// catch
// {
// await transaction.RollbackAsync(token);
// throw;
// }
// }
// public Task<IEnumerable<TDto>> GetCurrent(DateTimeOffset moment, CancellationToken token)
// {
// throw new NotImplementedException();
// }
// public Task<IEnumerable<DateOnly>> GetDatesChange(CancellationToken token)
// {
// throw new NotImplementedException();
// }
// public Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset date, CancellationToken token)
// {
// throw new NotImplementedException();
// }
// public async Task<int> InsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
// {
// using var transaction = dbContext.Database.BeginTransaction();
// try
// {
// var result = await InsertRangeWithoutTransaction(idUser, dtos, token);
// await transaction.CommitAsync(token);
// return result;
// }
// catch
// {
// await transaction.RollbackAsync(token);
// throw;
// }
// }
// protected abstract DatabaseFacade GetDataBase();
// public Task<int> MarkAsDeleted(int idUser, IEnumerable<int> ids, CancellationToken token)
// {
// throw new NotImplementedException();
// }
// public Task<int> UpdateOrInsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
// {
// throw new NotImplementedException();
// }
// public Task<int> UpdateRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
// {
// throw new NotImplementedException();
// }
// public Task<IEnumerable<TChangeLogDto>> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token)
// {
// throw new NotImplementedException();
// }
// private async Task<int> InsertRangeWithoutTransaction(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
// {
// var result = 0;
// if (dtos.Any())
// {
// var entities = dtos.Select(Convert);
// var creation = DateTimeOffset.UtcNow;
// var dbSet = dbContext.Set<TEntity>();
// foreach (var entity in entities)
// {
// entity.Id = default;
// entity.IdAuthor = idUser;
// entity.Creation = creation;
// entity.IdState = IChangeLogAbstract.IdStateActual;
// entity.IdEditor = null;
// entity.IdPrevious = null;
// entity.Obsolete = null;
// dbSet.Add(entity);
// }
// result += await SaveChangesWithExceptionHandling(token);
// }
// return result;
// }
// private async Task<int> SaveChangesWithExceptionHandling(CancellationToken token)
// {
// var result = await dbContext.SaveChangesAsync(token);
// return result;
// //try
// //{
// // var result = await dbContext.SaveChangesAsync(token);
// // return result;
// //}
// //catch (DbUpdateException ex)
// //{
// // if (ex.InnerException is PostgresException pgException)
// // TryConvertPostgresExceptionToValidateException(pgException);
// // throw;
// //}
// }
// //private static void TryConvertPostgresExceptionToValidateException(PostgresException pgException)
// //{
// // if (pgException.SqlState == PostgresErrorCodes.ForeignKeyViolation)
// // throw new ArgumentInvalidException("dtos", pgException.Message + "\r\n" + pgException.Detail);
// //}
//}

View File

@ -12,60 +12,60 @@ public interface IChangeLogRepository : ISyncWithDiscriminatorRepository<DataWit
/// <summary> /// <summary>
/// Добавление записей /// Добавление записей
/// </summary> /// </summary>
/// <param name="idUser">пользователь, который добавляет</param> /// <param name="idAuthor">пользователь, который добавляет</param>
/// <param name="idDiscriminator">ключ справочника</param> /// <param name="idDiscriminator">ключ справочника</param>
/// <param name="dtos"></param> /// <param name="dtos"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token); Task<int> AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);

idUser -> idAuthor, Такое имя позволит не читать комментарий. И совпадает с названием свойства Dto

idUser -> idAuthor, Такое имя позволит не читать комментарий. И совпадает с названием свойства Dto
/// <summary> /// <summary>
/// Пометить записи как удаленные /// Пометить записи как удаленные
/// </summary> /// </summary>
/// <param name="idUser"></param> /// <param name="idEditor"></param>
/// <param name="ids">ключи записей</param> /// <param name="ids">ключи записей</param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> MarkAsDeleted(Guid idUser, IEnumerable<Guid> ids, CancellationToken token); Task<int> MarkAsDeleted(Guid idEditor, IEnumerable<Guid> ids, CancellationToken token);
/// <summary> /// <summary>
/// Пометить записи как удаленные /// Пометить записи как удаленные
/// </summary> /// </summary>
/// <param name="idUser"></param> /// <param name="idEditor"></param>
/// <param name="idDiscriminator">дискриминатор таблицы</param> /// <param name="idDiscriminator">дискриминатор таблицы</param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> MarkAsDeleted(Guid idUser, Guid idDiscriminator, CancellationToken token); Task<int> MarkAsDeleted(Guid idEditor, Guid idDiscriminator, CancellationToken token);
/// <summary> /// <summary>
/// Очистить и добавить новые /// Очистить и добавить новые
/// </summary> /// </summary>
/// <param name="idUser"></param> /// <param name="idAuthor"></param>
/// <param name="idDiscriminator"></param> /// <param name="idDiscriminator"></param>
/// <param name="dtos"></param> /// <param name="dtos"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> ClearAndInsertRange(Guid idUser, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token); Task<int> ClearAndAddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
/// <summary> /// <summary>
/// Редактирование записей /// Редактирование записей
/// </summary> /// </summary>
/// <param name="idUser">пользователь, который редактирует</param> /// <param name="idEditor">пользователь, который редактирует</param>
/// <param name="idDiscriminator"></param>
/// <param name="dtos"></param> /// <param name="dtos"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token); Task<int> UpdateRange(Guid idEditor, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);

DataWithWellDepthAndSectionDto содержит Guid Id, Поэтому Guid idDiscriminator не нужен.

DataWithWellDepthAndSectionDto содержит Guid Id, Поэтому Guid idDiscriminator не нужен.
/// <summary> /// <summary>
/// Получение актуальных записей на определенный момент времени (с пагинацией) /// Получение актуальных записей на определенный момент времени (с пагинацией)
/// </summary> /// </summary>
/// <param name="idDiscriminator"></param> /// <param name="idDiscriminator"></param>
/// <param name="moment">текущий момент времени</param> /// <param name="moment">текущий момент времени</param>
/// <param name="request">параметры запроса</param> /// <param name="filterRequest">параметры запроса фильтрации</param>
/// <param name="paginationRequest">параметры запроса пагинации</param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<PaginationContainer<DataWithWellDepthAndSectionDto>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest request, CancellationToken token); Task<PaginationContainer<DataWithWellDepthAndSectionDto>> GetByDate(Guid idDiscriminator, DateTimeOffset moment, SectionPartRequest filterRequest, PaginationRequest paginationRequest, CancellationToken token);
/// <summary> /// <summary>
/// Получение измененных записей за период времени /// Получение измененных записей за период времени

View File

@ -7,7 +7,7 @@ namespace Persistence.Repositories;
/// </summary> /// </summary>
public interface ITableDataRepository<TDto, TRequest> public interface ITableDataRepository<TDto, TRequest>
where TDto : class, new() where TDto : class, new()
where TRequest : Request where TRequest : PaginationRequest
{ {
/// <summary> /// <summary>
/// Получить страницу списка объектов /// Получить страницу списка объектов