featute/ChangeLog #6
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "featute/ChangeLog"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
https://project.ddrilling.ru/projects/persistance-service/work_packages/400/activity
featute/ChangeLogto WIP: featute/ChangeLog@ -0,0 +26,4 @@
[FromBody] DataWithWellDepthAndSectionDto dto,
CancellationToken token)
{
var userId = User.GetUserId<Guid>();
Тут Да же проблема что и с сообщениями. Id системы, которая нам эти данные отправила, сюда не очень подходит
Решили пока оставить, как есть
@ -0,0 +49,4 @@
public async Task<IActionResult> Delete(Guid id, CancellationToken token)
{
var userId = User.GetUserId<Guid>();
var result = await repository.MarkAsDeleted(userId, [id], token);
Если метод repository.MarkAsDeleted вернет 0 (удаляемая запись отсутствует), то методы delete должны возвращать NoContent
@ -0,0 +11,4 @@
{
private const string BaseRoute = "/api/ChangeLog";
//[Get($"{BaseRoute}/current")]
лишние комменты
@ -0,0 +6,4 @@
/// <summary>
/// Часть записи, описывающая изменение
/// </summary>
public interface IChangeLog
Кажется этот интерфейс уже не нужен
Он все еще не нужен..
@ -32,3 +32,3 @@
/// <summary>
/// Id состояния
/// Ключ следующей записи
Заменившей
@ -0,0 +11,4 @@
/// </summary>
public class DataWithWellDepthAndSectionDto
{
public DataWithWellDepthAndSectionDto()
пустые конструкторы не нужны
@ -0,0 +39,4 @@
/// <summary>
/// Объект записи
/// </summary>
public required IDictionary<string, object> Value { get; set; } = default!;
= default!; - лишнее
@ -0,0 +3,4 @@
/// <summary>
/// Часть записи описывающая изменение
/// </summary>
public interface IChangeLogDto
А зачем он тогда нужен?
@ -0,0 +5,4 @@
using System.Threading.Tasks;
namespace Persistence.Models;
public class ProcessMapRotorDto : IChangeLogDto
delete
@ -0,0 +9,4 @@
/// <summary>
/// Кол-во записей пропущенных с начала таблицы в запросе от api
/// </summary>
public int? Skip { get; set; }
Skip/Take - используются только с PaginationContainer. Поэтому предлагаю сделать из обязательными, но со значениями по умолчанию.
@ -0,0 +3,4 @@
/// <summary>
/// Запрос для фильтрации данных по секции и глубине
/// </summary>
public class SectionPartRequest : Request
Возможно тут было бы проще без наследования
@ -53,3 +20,1 @@
/// <param name="token"></param>
/// <returns></returns>
Task<int> ClearAndInsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token);
Task<int> InsertRange(Guid idUser, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
idUser -> idAuthor, Такое имя позволит не читать комментарий. И совпадает с названием свойства Dto
@ -86,3 +56,3 @@
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<TDto>> GetCurrent(DateTimeOffset moment, CancellationToken token);
Task<int> UpdateRange(Guid idUser, Guid idDiscriminator, IEnumerable<DataWithWellDepthAndSectionDto> dtos, CancellationToken token);
DataWithWellDepthAndSectionDto содержит Guid Id, Поэтому Guid idDiscriminator не нужен.
@ -89,0 +75,4 @@
/// <param name="dateEnd"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<ChangeLogDto>> GetChangeLogForDate(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
Лучше ForDate -> ForInterval
Кстати в вместо аргументов dateBegin, dateEnd можно использовать DatesRangeDto
WIP: featute/ChangeLogto featute/ChangeLog@ -0,0 +20,4 @@
}
[HttpPost]
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
Не тот хттп код
И дальше тоже есть.
@ -0,0 +22,4 @@
[HttpPost]
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
public async Task<IActionResult> Add(
Guid idDiscriminator,
idDiscriminator лучше сделать частью route
@ -0,0 +167,4 @@
var result = await repository.GetDatesRange(idDiscriminator, token);
if(result is null)
return NoContent();
Нужно добавить все коды возврата в аттрибуты метода, чтобы в сваггере они отображались и пользователи знали что при обработке ответа такой код может прилететь и им его как-то надо обработать.
@ -0,0 +12,4 @@
/// <summary>
/// Ключ записи
/// </summary>
[Key, Column("Id")]
Договаривались в моделях БД не указывать имя колонки, чтобы оно совпадало с именем свойства.
А чтобы модель визуально оставалась узнаваемой как модель решили указывать атрибут комментария..
@ -0,0 +24,4 @@
}
[Fact]
public async Task ClearAndInsertRange()
Этот кейс проверяет на пустой базе и не охватывает логику отмечания существующих в БД данных как удаленные.
@ -0,0 +20,4 @@
foreach (var dto in dtos)
{
var entity = CreateEntityFromDto(idAuthor, idDiscriminator, dto);
db.Set<ChangeLog>().Add(entity);
db.Set() хоть и не дорогой но не бесплатный:) Получать его для каждой dto как-то не оправданно.
@ -0,0 +32,4 @@
{
var query = db.Set<ChangeLog>().Where(s => ids.Contains(s.Id));
var entities = await query.ToArrayAsync(token);
Стоит проверить, что количество записей совпадает с количеством ids. Если не совпадает - исключение
@ -0,0 +50,4 @@
return result;
}
private async Task<int> Clear(Guid idEditor, IEnumerable<ChangeLog> entities, CancellationToken token)
немного смущает название
@ -0,0 +54,4 @@
{
var updateTime = DateTimeOffset.UtcNow;
foreach (var entity in entities)
Думаю тут будет разумно проверить, что помечаемые записи еще не устарели. И если мы собираемся отредактировать устаревшее, то падаем в исключение.
@ -0,0 +67,4 @@
{
var result = 0;
using var transaction = await db.Database.BeginTransactionAsync(token);
try
try-catch тут и дальше не нужен. Rollback ролбэк будет вызван финализатором транзакции, если не был вызван комит
@ -0,0 +100,4 @@
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
@ -0,0 +136,4 @@
return result;
}
private IQueryable<ChangeLog> BuildQuery(Guid idDiscriminator, DateTimeOffset momentUtc, SectionPartRequest request)
"Build" - намекает на наличие билдера, а его нет. (можно подумать чтобы его завести:))
@ -0,0 +140,4 @@
{
var query = db.Set<ChangeLog>()
.Where(e => e.IdDiscriminator == idDiscriminator)
.Where(e => e.Creation <= momentUtc)
Мы не доверяем пользователям и все равно приводим к UTC
@ -0,0 +163,4 @@
{
var query = db.Set<ChangeLog>().Where(s => s.IdDiscriminator == idDiscriminator);
var min = new DateTimeOffset(dateBegin.Year, dateBegin.Month, dateBegin.Day, 0, 0, 0, TimeSpan.Zero);
Тут ошибка в часовых поясах.
var min = new DateTimeOffset(dateBegin.ToUniversalTime().Date, TimeSpan.Zero);
@ -0,0 +181,4 @@
private async Task<PaginationContainer<DataWithWellDepthAndSectionDto>> BuildPaginationContainer(IQueryable<ChangeLog> query, PaginationRequest request, CancellationToken token)
{
var result = new PaginationContainer<DataWithWellDepthAndSectionDto>
result лучше собирать, когда для него уже есть все данные
@ -0,0 +206,4 @@
.Take(result.Take)
.ToArrayAsync(token);
var dtos = entities.Select(e => e.Adapt<DataWithWellDepthAndSectionDto>());
Конвертацию лучше вынести в метод. Так связь с маппером слабже и преобразование единообразное.
@ -0,0 +242,4 @@
{
var entity = new ChangeLog()
{
Id = default,
Не все базы так поймут. Лучше для новых сущностей их генерировать самостоятельно (в идеале по седьмой версии).
@ -0,0 +279,4 @@
.Select(group => new
{
Min = group.Min(e => e.Creation),
Max = group.Max(e => e.Creation),
Не учитывает даты устаревания
@ -0,0 +101,4 @@
var result = 0;
using var transaction = await db.Database.BeginTransactionAsync(token);
try
try-catch тут и дальше не нужен. Rollback ролбэк будет вызван финализатором транзакции, если не был вызван комит