diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs index 07e10e7b1..764f821ef 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs @@ -33,7 +33,8 @@ namespace Ordering.API.Application.Commands } orderToUpdate.SetCancelledStatus(); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + await _orderRepository.UnitOfWork.SaveChangesAsync(cancellationToken); + return true; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs index b2fff253d..d427a7117 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs @@ -57,8 +57,8 @@ _orderRepository.Add(order); - return await _orderRepository.UnitOfWork - .SaveEntitiesAsync(cancellationToken); + await _orderRepository.UnitOfWork.SaveChangesAsync(cancellationToken); + return true; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs index f329d7c3f..05e080acf 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs @@ -10,7 +10,7 @@ namespace Ordering.API.Application.Commands { // Regular CommandHandler public class SetAwaitingValidationOrderStatusCommandHandler : IRequestHandler - { + { private readonly IOrderRepository _orderRepository; public SetAwaitingValidationOrderStatusCommandHandler(IOrderRepository orderRepository) @@ -27,13 +27,14 @@ namespace Ordering.API.Application.Commands public async Task Handle(SetAwaitingValidationOrderStatusCommand command, CancellationToken cancellationToken) { var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); - if(orderToUpdate == null) + if (orderToUpdate == null) { return false; } orderToUpdate.SetAwaitingValidationStatus(); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + await _orderRepository.UnitOfWork.SaveChangesAsync(cancellationToken); + return true; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs index f0400ec16..e2aa9015f 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs @@ -10,7 +10,7 @@ namespace Ordering.API.Application.Commands { // Regular CommandHandler public class SetPaidOrderStatusCommandHandler : IRequestHandler - { + { private readonly IOrderRepository _orderRepository; public SetPaidOrderStatusCommandHandler(IOrderRepository orderRepository) @@ -30,13 +30,14 @@ namespace Ordering.API.Application.Commands await Task.Delay(10000, cancellationToken); var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); - if(orderToUpdate == null) + if (orderToUpdate == null) { return false; } orderToUpdate.SetPaidStatus(); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + await _orderRepository.UnitOfWork.SaveChangesAsync(cancellationToken); + return true; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs index b76c16ec6..a45012ed9 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs @@ -36,7 +36,8 @@ namespace Ordering.API.Application.Commands } orderToUpdate.SetStockConfirmedStatus(); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + await _orderRepository.UnitOfWork.SaveChangesAsync(cancellationToken); + return true; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs index 98d8dfd77..ef8661731 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs @@ -10,7 +10,7 @@ namespace Ordering.API.Application.Commands { // Regular CommandHandler public class SetStockRejectedOrderStatusCommandHandler : IRequestHandler - { + { private readonly IOrderRepository _orderRepository; public SetStockRejectedOrderStatusCommandHandler(IOrderRepository orderRepository) @@ -30,14 +30,15 @@ namespace Ordering.API.Application.Commands await Task.Delay(10000, cancellationToken); var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); - if(orderToUpdate == null) + if (orderToUpdate == null) { return false; - } + } orderToUpdate.SetCancelledStatusWhenStockIsRejected(command.OrderStockItems); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + await _orderRepository.UnitOfWork.SaveChangesAsync(cancellationToken); + return true; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs index 4e1173c05..538631e3a 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs @@ -33,7 +33,8 @@ namespace Ordering.API.Application.Commands } orderToUpdate.SetShippedStatus(); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + await _orderRepository.UnitOfWork.SaveChangesAsync(cancellationToken); + return true; } } diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs index 5b8f19b00..df214c642 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs @@ -55,8 +55,7 @@ namespace Ordering.API.Application.DomainEventHandlers.OrderStartedEvent _buyerRepository.Update(buyer) : _buyerRepository.Add(buyer); - await _buyerRepository.UnitOfWork - .SaveEntitiesAsync(cancellationToken); + await _buyerRepository.UnitOfWork.SaveChangesAsync(cancellationToken); var orderStatusChangedTosubmittedIntegrationEvent = new OrderStatusChangedToSubmittedIntegrationEvent(orderStartedEvent.Order.Id, orderStartedEvent.Order.OrderStatus.Name, buyer.Name); await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedTosubmittedIntegrationEvent); diff --git a/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs b/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs index 810f0b2af..df79ef38f 100644 --- a/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs +++ b/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs @@ -7,6 +7,5 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork public interface IUnitOfWork : IDisposable { Task SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)); - Task SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken)); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs index d7991b81c..429237df1 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs @@ -52,7 +52,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure modelBuilder.ApplyConfiguration(new BuyerEntityTypeConfiguration()); } - public async Task SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken)) + public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default) { // Dispatch Domain Events collection. // Choices: @@ -64,9 +64,22 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure // After executing this line all the changes (from the Command Handler and Domain Event Handlers) // performed through the DbContext will be committed - var result = await base.SaveChangesAsync(cancellationToken); + return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + } - return true; + public override int SaveChanges(bool acceptAllChangesOnSuccess) + { + // Dispatch Domain Events collection. + // Choices: + // A) Right BEFORE committing data (EF SaveChanges) into the DB will make a single transaction including + // side effects from the domain event handlers which are using the same DbContext with "InstancePerLifetimeScope" or "scoped" lifetime + // B) Right AFTER committing data (EF SaveChanges) into the DB will make multiple transactions. + // You will need to handle eventual consistency and compensatory actions in case of failures in any of the Handlers. + _mediator.DispatchDomainEventsAsync(this).Wait(); + + // After executing this line all the changes (from the Command Handler and Domain Event Handlers) + // performed through the DbContext will be committed + return base.SaveChanges(acceptAllChangesOnSuccess); } public async Task BeginTransactionAsync()