对控制器函数的多次调用会导致问题(ASP.NET MVC Web 应用程序中的 EF Core)
Posted
技术标签:
【中文标题】对控制器函数的多次调用会导致问题(ASP.NET MVC Web 应用程序中的 EF Core)【英文标题】:Multiple calls to a controller's function causes problems (EF Core in an ASP.NET MVC web app) 【发布时间】:2021-11-03 02:03:26 【问题描述】:我在 ASP.NET MVC Web 应用程序中使用 EF Core。
这是一家在线餐厅。我想让用户更改购物车项目的数量(仅在这一点添加更多)并通过它来更新他的cartItemPrice
和他的cartTotalPrice
(购物车可以包含很少的购物车项目,每个购物车项目都可以包含少量菜肴)。
在测试代码后,它工作正常,只有当我当时调用AddOne
方法一时,cartItemPrice
和CartTotalPrice
都应该更新。
当我多次调用该方法时问题开始(通过快速单击..双击导致问题的实例)。
该问题导致cartItemPrice
有时会更改,有时不会更改,而CartTotalPrice
总是更改。
我使用这个标签从 View/Carts 调用 AddOne
方法:
<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();
这里出了什么问题,是否可以修复?
谢谢。
【问题讨论】:
1) 将并发列添加到您的架构中。 2)调用保存更改一次,或在事务中。 3) 捕获并重试请求。和/或通过查询按需计算总价。 似乎 [ConcurrencyCheck] 修复了它。谢谢@JeremyLakeman 【参考方案1】:当服务器处理一个请求时,另一个请求正在做同样的事情,并且你有数据竞争。
你可以通过两种方式解决这个问题:
交易
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]
,如documentation 中指定的那样。
然后抓住DbUpdateConcurrencyException
并重新开始更新价格。 Handling Concurrency Conflicts
【讨论】:
似乎 [ConcurrencyCheck] 修复了它。谢谢以上是关于对控制器函数的多次调用会导致问题(ASP.NET MVC Web 应用程序中的 EF Core)的主要内容,如果未能解决你的问题,请参考以下文章
带有 ADO .NET 的 ASP .NET MVC 会导致问题吗?