c# - 对控制器函数的多次调用会导致问题(ASP.NET MVC Web 应用程序中的 EF Core)
问题描述
我在 ASP.NET MVC Web 应用程序中使用 EF Core。
这是一家在线餐厅。我想让用户更改购物车项目的数量(仅在这一点上添加更多),然后更新他的cartItemPrice
和他的cartTotalPrice
(购物车可以包含很少的购物车项目,每个购物车项目可以包含很少的菜)。
测试代码后,它工作正常,只有当我当时调用AddOne
方法一时,cartItemPrice
两者CartTotalPrice
都应该更新。
当我多次调用该方法时问题就开始了(通过快速单击..双击例如导致问题)。
这个问题有时会导致cartItemPrice
改变,有时不会改变,而CartTotalPrice
总是改变。
我使用这个标签AddOne
从 View/Carts 调用方法:
<div class="quantity">
<a asp-action="AddOne" asp-controller="Carts" asp-route-id="@ci.Id" class="add quantity-btn col-3">+</a>
</div>
我尝试使用 async 和 await 并且没有它们,两种方式都给出了同样糟糕的结果。
Controllers/CartsController 的功能:
异步/等待:
public async Task AddToTotalPrice(double price)
{
var user = GetCurrentUserName();
var cart = await _context.Cart.FirstOrDefaultAsync(s => s.UserName == user);
cart.CartTotalPrice += price;
await _context.SaveChangesAsync();
}
public async Task AddOne(int id)
{
var cartitem = await _context.CartItem.Include(d => d.Dish).FirstOrDefaultAsync(s => s.Id == id);
var u = GetCurrentUserName();
var c = _context.Cart.FirstOrDefault(p => p.UserName == u);
if (cartitem != null)
{
if (cartitem.CartId != c.Id)
{
return;
}
cartitem.Quantity += 1;
cartitem.cartItemPrice = cartitem.Dish.Price * cartitem.Quantity;
await AddToTotalPrice(cartitem.Dish.Price);
await _context.SaveChangesAsync();
}
}
没有异步/等待:
public void AddToTotalPrice(double price)
{
var user = GetCurrentUserName();
var cart = _context.Cart.FirstOrDefault(s => s.UserName == user);
cart.cartTotalPrice += price;
_context.SaveChanges();
}
public void AddOne(int id)
{
var cartitem = _context.CartItem.Include(d => d.Dish).FirstOrDefault(s => s.Id == id);
var u = GetCurrentUserName();
var c = _context.Cart.FirstOrDefault(p => p.UserName == u);
if (cartitem != null)
{
if (cartitem.CartId != c.Id)
{
return;
}
cartitem.Quantity += 1;
cartitem.cartItemPrice = cartitem.Dish.Price * cartitem.Quantity;
AddToTotalPrice(cartitem.Dish.Price);
_context.SaveChanges();
}
}
这里有什么问题,如果可以解决?
谢谢。
解决方案
当服务器处理一个请求时,另一个请求正在做同样的事情,并且您有数据竞争。
您可以通过两种方式解决此问题:
交易
public async Task AddToTotalPrice(double price)
{
var user = GetCurrentUserName();
var cart = await _context.Cart.FirstOrDefaultAsync(s => s.UserName == user);
cart.CartTotalPrice += price;
}
public async Task AddOne(int id)
{
using var tran = _context.Database.BeginTransactionAsync();
var cartitem = await _context.CartItem.Include(d => d.Dish).FirstOrDefaultAsync(s => s.Id == id);
var u = GetCurrentUserName();
var c = _context.Cart.FirstOrDefault(p => p.UserName == u);
if (cartitem != null)
{
if (cartitem.CartId != c.Id)
{
return;
}
cartitem.Quantity += 1;
cartitem.cartItemPrice = cartitem.Dish.Price * cartitem.Quantity;
await AddToTotalPrice(cartitem.Dish.Price);
await _context.SaveChangesAsync();
}
await tran.CommitAsync();
}
并发令牌
添加到文档中指定的Cart.CartTotalPrice
属性。[ConcurrencyCheck]
并再次捕获DbUpdateConcurrencyException
并重新开始更新价格。处理并发冲突
推荐阅读
- nginx - 有主动/被动队列时如何配置 Nginx 以平衡 weblogic
- python - 将字符串中的值移动到列表中下一个字符串的开头
- mysql - NodeJS 和 MySQL:导入带有关联的 CSV 数据
- css - 链接变成蓝色的fr。当我在 CSS 中添加过渡时间时
- reactjs - 从子组件设置状态并使用 Context API 将其传递给父组件
- ios - 当我开始使用 WKWebViewOnly 时,Auth0 登录停止工作
- angular - 如果我使用 compareWith,如何从 ngSelected 获取选定值?
- javascript - 提取特定 ID 的 Google 脚本
- r - Crowly 的第 2.8.6 章 R 书
- azure - 通过 cmdlet 或 rest api 在 Azure 合作伙伴中心注册 Azure 应用