我有一个基于 ASP.NET 样板(Angular 前端和 MSSQL 数据库)的网上商店。
网上商店包含物品,我想保留这些物品的库存。每次创建订单时,都会更新库存。所以基本上我有一个包含网上商店、商品和订单的数据库。
我有这些对象的存储库和管理器。
一切正常,但是当两个客户端同时加载网上商店时会出现问题。
Client1 打开网页:
- 网店1
- 第 1 项:“10 项可用”
- 第 2 项:“8 项可用”
Client2同时打开网页:
- 网店1
- 第 1 项:“10 项可用”
- 第 2 项:“8 项可用”
购买所有可用物品的第一个应该能够创建订单,第二个应该得到错误。
创建订单后,后端会检查是否有足够的可用商品。但是,当在创建第一个客户端的订单之前加载网上商店时,第二个客户端不知道更新的库存,并且也能够创建订单。
这意味着可以出售 20 件 Item1!
如何在后端的两个会话之间“同步”数据?加载网上商店时,数据似乎以某种方式缓存在后端。
创建订单函数
public async Task<CreateOrderResponseDto> Create(CreateOrderDto input, long? userId)
{
input.OrderItems.ForEach(async o =>
{
if (!(await _salesItemManager.ReserveStock(o.SalesItemId, o.Quantity)).IsSuccess)
{
throw CodeException.ToAbpValidationException("OrderItem", "OrderItemCreate");
}
});
var salesPage = await _salesPageManager.Get(input.SalesPageId, false);
if (salesPage.GetState() != StatePage.Published)
{
throw CodeException.ToAbpValidationException("Order", "PageNotAvailable");
}
if (salesPage.CommentsRequired.HasValue && salesPage.CommentsRequired.Value)
{
if (string.IsNullOrWhiteSpace(input.Description))
{
throw CodeException.ToAbpValidationException("Order", "CommentsRequired");
}
}
var order = new Order
{
Address = input.Address,
City = input.City,
LastName = input.LastName,
Name = input.Name,
PostalCode = input.PostalCode,
Email = input.Email,
PhoneNumber = input.PhoneNumber,
Description = input.Description,
SalesPage = salesPage
};
try
{
order.Price = await _salesItemManager.GetPriceByOrders(input.OrderItems);
order = await _orderRepository.InsertAsync(order);
input.OrderItems.ForEach(async o =>
{
var orderItem = new OrderItem();
orderItem.SalesItemId = o.SalesItemId;
orderItem.OrderId = order.Id;
orderItem.Quantity = o.Quantity;
await _orderItemRepository.InsertAsync(orderItem);
});
if (input.SelectedSalesPageOptionId.HasValue)
{
order.SalesOption = await _salesPageManager.GetOption(input.SelectedSalesPageOptionId.Value);
}
}
catch (Exception e)
{
throw CodeException.ToAbpValidationException("OrderItem", "OrderItemCreate");
}
if (userId.HasValue && salesPage.User.Id == userId.Value)
{
var payment = await _paymentManager.CreateManualPayment(order, input.IsPaid);
order.Payment = payment;
return new CreateOrderResponseDto() { IsSuccess = true, PaymentUrl = string.Empty, OrderId = order.Id.ToString() };
}
else
{
var payment = await _paymentManager.CreatePayment(order);
order.Payment = payment;
return new CreateOrderResponseDto() { IsSuccess = true, PaymentUrl = payment.PaymentUrl, OrderId = order.Id.ToString() };
}
}
ReserveStock函数
public async Task<GeneralDto> ReserveStock(Guid itemId, int quantity)
{
var salesItem = await _salesItemRepository.GetAsync(itemId);
if (salesItem == null || salesItem.Stock == null || salesItem.ReservedStock == null)
return new GeneralDto() { IsSuccess = false };
if (salesItem.Stock < quantity)
{
return new GeneralDto() { IsSuccess = false };
}
salesItem.Stock -= quantity;
salesItem.ReservedStock += quantity;
try
{
await _salesItemRepository.UpdateAsync(salesItem);
}
catch (Exception e)
{
throw CodeException.ToAbpValidationException("SalesItem", "SalesItemUpdate");
}
return new GeneralDto() { IsSuccess = true };
}