diff --git a/OutOfSchool/OutOfSchool.DataAccess/Repository/EntityRepositoryBase.cs b/OutOfSchool/OutOfSchool.DataAccess/Repository/EntityRepositoryBase.cs index fe6a94fed5..8560cfc460 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Repository/EntityRepositoryBase.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Repository/EntityRepositoryBase.cs @@ -77,6 +77,28 @@ public virtual async Task RunInTransaction(Func> operation) }); } + /// + public virtual async Task RunInTransaction(Func operation) + { + var executionStrategy = dbContext.Database.CreateExecutionStrategy(); + + await executionStrategy.ExecuteAsync( + async () => + { + await using IDbContextTransaction transaction = await dbContext.Database.BeginTransactionAsync(); + try + { + await operation().ConfigureAwait(false); + await transaction.CommitAsync().ConfigureAwait(false); + } + catch (Exception ex) + { + await transaction.RollbackAsync().ConfigureAwait(false); + throw; + } + }); + } + /// public virtual async Task Delete(TEntity entity) { diff --git a/OutOfSchool/OutOfSchool.DataAccess/Repository/IEntityRepository.cs b/OutOfSchool/OutOfSchool.DataAccess/Repository/IEntityRepository.cs index aa5bb06c94..020db88a0e 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Repository/IEntityRepository.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Repository/IEntityRepository.cs @@ -43,6 +43,13 @@ public interface IEntityRepositoryBase /// A representing the result of the asynchronous operation. Task RunInTransaction(Func> operation); + /// + /// Runs operation in transaction without result. + /// + /// Method that represents the operation. + /// A representing the result of the asynchronous operation. + Task RunInTransaction(Func operation); + /// /// Update information about element. /// diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/ProviderServiceTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/ProviderServiceTests.cs index 1dbd74b88c..53150ced86 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/ProviderServiceTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/ProviderServiceTests.cs @@ -939,6 +939,8 @@ public async Task Block_ReturnsProviderBlockDto_IfDtoIsValid() .ReturnsAsync(provider); providersRepositoryMock.Setup(r => r.UnitOfWork.CompleteAsync()) .ReturnsAsync(It.IsAny()); + providersRepositoryMock.Setup(r => r.RunInTransaction(It.IsAny>>())) + .ReturnsAsync(providerBlockDto); // Act var result = await providerService.Block(providerBlockDto).ConfigureAwait(false); diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs index 3623e800d8..b02c547e94 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Data; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; @@ -303,20 +304,23 @@ public async Task Block(ProviderBlockDto providerBlockDto) // TODO: validate if current user has permission to block/unblock the provider provider.IsBlocked = providerBlockDto.IsBlocked; provider.BlockReason = providerBlockDto.IsBlocked ? providerBlockDto.BlockReason : null; - await providerRepository.UnitOfWork.CompleteAsync().ConfigureAwait(false); - - // TODO What's happen if previous action will not successfull? - var workshops = await workshopServiceCombiner - .BlockByProvider(provider) - .ConfigureAwait(false); - foreach (var workshop in workshops) + await providerRepository.RunInTransaction(async () => { - logger.LogInformation($"IsBlocked property with povider Id = {provider.Id} " + - $"in workshops with Id = {workshop.Id} updated successfully."); - } + await providerRepository.UnitOfWork.CompleteAsync().ConfigureAwait(false); + + var workshops = await workshopServiceCombiner + .BlockByProvider(provider) + .ConfigureAwait(false); + + foreach (var workshop in workshops) + { + logger.LogInformation($"IsBlocked property with povider Id = {provider.Id} " + + $"in workshops with Id = {workshop.Id} updated successfully."); + } - logger.LogInformation($"Provider(id) {providerBlockDto.Id} IsBlocked was changed to {provider.IsBlocked}"); + logger.LogInformation($"Provider(id) {providerBlockDto.Id} IsBlocked was changed to {provider.IsBlocked}"); + }); return providerBlockDto; }