using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Persistence.Models; using System.Linq; namespace Persistence.Repositories; public abstract class AbstractChangeLogRepository : IChangeLogRepository where TDto : class, new() where TEntity : class, IChangeLogAbstract where TChangeLogDto : ChangeLogDto { private readonly DbContext dbContext; protected AbstractChangeLogRepository(DbContext dbContext) { this.dbContext = dbContext; } public abstract TEntity Convert(TDto entity); public async Task Clear(int idUser, TRequest request, CancellationToken token) { 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 ClearAndInsertRange(int idUser, TRequest request, IEnumerable dtos, CancellationToken token) { var result = 0; using var transaction = await dbContext.Database.BeginTransactionAsync(token); try { result += await Clear(idUser, request, token); result += await InsertRangeWithoutTransaction(idUser, dtos, token); await transaction.CommitAsync(token); return result; } catch { await transaction.RollbackAsync(token); throw; } } public Task> GetCurrent(TRequest request, CancellationToken token) { throw new NotImplementedException(); } public Task> GetDatesChange(TRequest request, CancellationToken token) { throw new NotImplementedException(); } public Task> GetGtDate(DateTimeOffset date, CancellationToken token) { throw new NotImplementedException(); } public async Task InsertRange(int idUser, IEnumerable dtos, CancellationToken token) { this.dbContext.Set(); var db = GetDataBase(); using var transaction = db.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 MarkAsDeleted(int idUser, IEnumerable ids, CancellationToken token) { throw new NotImplementedException(); } public Task UpdateOrInsertRange(int idUser, IEnumerable dtos, CancellationToken token) { throw new NotImplementedException(); } public Task UpdateRange(int idUser, IEnumerable dtos, CancellationToken token) { throw new NotImplementedException(); } public Task> GetChangeLogForDate(TRequest request, DateOnly? date, CancellationToken token) { throw new NotImplementedException(); } private async Task InsertRangeWithoutTransaction(int idUser, IEnumerable dtos, CancellationToken token) { var result = 0; if (dtos.Any()) { var entities = dtos.Select(Convert); var creation = DateTimeOffset.UtcNow; var dbSet = dbContext.Set(); 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 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); //} }