订单创建命令处理程序

This commit is contained in:
hello 2024-09-10 22:07:43 +08:00
parent 923089b83b
commit 348ea248a6
3 changed files with 89 additions and 3 deletions

View File

@ -0,0 +1,53 @@
using HelloShop.OrderingService.Extensions;
using HelloShop.OrderingService.Infrastructure;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System.Data;
namespace HelloShop.OrderingService.Behaviors
{
public class TransactionBehavior<TRequest, TResponse>(OrderingServiceDbContext dbContext, ILoggerFactory loggerFactory) : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
private readonly ILogger<TransactionBehavior<TRequest, TResponse>> _logger = loggerFactory.CreateLogger<TransactionBehavior<TRequest, TResponse>>();
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
TResponse? response = default;
string typeName = request.GetGenericTypeName();
try
{
if (dbContext.Database.CurrentTransaction != null)
{
return await next();
}
var strategy = dbContext.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
using var transaction = await dbContext.Database.BeginTransactionAsync(IsolationLevel.ReadCommitted);
using (_logger.BeginScope(new List<KeyValuePair<string, object>> { new("TransactionContext", transaction.TransactionId) }))
{
_logger.LogInformation("Begin transaction {TransactionId} for {CommandName} {Command}", transaction.TransactionId, typeName, request);
response = await next();
_logger.LogInformation("Commit transaction {TransactionId} for {CommandName}", transaction.TransactionId, typeName);
}
await transaction.CommitAsync();
});
return response ?? throw new ApplicationException($"Command {typeName} returned null response");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error Handling transaction for {CommandName} {Request}", typeName, request);
throw;
}
}
}
}

View File

@ -1,16 +1,48 @@
// Copyright (c) HelloShop Corporation. All rights reserved. // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information. // See the license file in the project root for more information.
using AutoMapper;
using HelloShop.OrderingService.Entities.Buyers;
using HelloShop.OrderingService.Entities.Orders;
using HelloShop.OrderingService.Infrastructure;
using HelloShop.OrderingService.Services; using HelloShop.OrderingService.Services;
using MediatR; using MediatR;
using Microsoft.EntityFrameworkCore;
namespace HelloShop.OrderingService.Commands.Orders namespace HelloShop.OrderingService.Commands.Orders
{ {
public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand, bool> public class CreateOrderCommandHandler(OrderingServiceDbContext dbContext, IMapper mapper) : IRequestHandler<CreateOrderCommand, bool>
{ {
public Task<bool> Handle(CreateOrderCommand request, CancellationToken cancellationToken) public async Task<bool> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
{ {
throw new NotImplementedException(); Address address = mapper.Map<Address>(request);
IEnumerable<OrderItem> orderItems = mapper.Map<IEnumerable<OrderItem>>(request.OrderItems);
Buyer? buyer = await dbContext.Set<Buyer>().FindAsync([request.UserId], cancellationToken);
if (buyer == null)
{
buyer = new() { Id = request.UserId, Name = request.UserName };
await dbContext.AddAsync(buyer, cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
}
PaymentMethod? paymentMethod = await dbContext.Set<PaymentMethod>().SingleOrDefaultAsync(pm => pm.BuyerId == buyer.Id && pm.CardNumber == request.CardNumber, cancellationToken);
if (paymentMethod == null)
{
paymentMethod = new() { BuyerId = buyer.Id, Alias = request.CardAlias, CardNumber = request.CardNumber, SecurityNumber = request.CardSecurityNumber, CardHolderName = request.CardHolderName, Expiration = request.CardExpiration };
await dbContext.AddAsync(paymentMethod, cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
}
Order order = new(buyer.Id, address, orderItems) { PaymentMethodId = paymentMethod.Id };
await dbContext.AddAsync(order, cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
return await Task.FromResult(true);
} }
} }

View File

@ -29,6 +29,7 @@ namespace HelloShop.OrderingService.Extensions
options.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()); options.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
options.AddBehavior(typeof(LoggingBehavior<,>)); options.AddBehavior(typeof(LoggingBehavior<,>));
options.AddBehavior(typeof(ValidatorBehavior<,>)); options.AddBehavior(typeof(ValidatorBehavior<,>));
options.AddBehavior(typeof(TransactionBehavior<,>));
}); });
builder.Services.AddModelMapper().AddModelValidator(); builder.Services.AddModelMapper().AddModelValidator();