错误:System.Data.SqlClient.SqlException:不允许新事务,因为会话中正在运行其他线程

本文关键字:会话 因为 线程 其他 运行 事务 SqlClient Data System SqlException 不允许 | 更新日期: 2023-09-27 18:34:44

我正在尝试单独更新每个产品,其中多个产品可以在一个订单中找到。当我按提交/更新时,我将订单 ID 与新产品数量一起发送到控制器。这是我看到的错误:

System.Data.SqlClient.SqlException:不允许新事务 因为会话中还有其他线程在运行。

这是重定向到表单的控制器。

[HttpGet]
    [Authorize(Roles = "ADM")]
    public ActionResult UpdateDetails(Guid id)
    {
        BusinessLayer.Orders blorder = new BusinessLayer.Orders();
        return View(blorder.GetOrderDetailsByOrderId(id));
    }

这是形式。

@model IQueryable<CommonLayer.ORDERDETAIL>
@{
    ViewBag.Title = "UpdateDetails";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>UpdateDetails</h2>

<table class="table table-striped" style="font-size:medium;">
    <tr>
        <th>
            Order Details ID
        </th>
        <th>
            Price
        </th>
        <th>
            VAT Rate
        </th>
        <th>
            Quantity
        </th>
    </tr>
    @foreach (var item in Model)
    {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.OrderDetailsId)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.ProductPrice)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.ProductVATRate)
                </td>
                <td>
                    <form action="/order/updatedetails/@item.OrderDetailsId" method="post" enctype="multipart/form-data">
                        <input type="text" name="prodqty" value="@item.ProductQuantity" />
                        <div class="form-group">
                            <div class="col-md-offset-2 col-md-10">
                                <br />
                                <input type="submit" value="Update" class="btn btn-primary" />
                            </div>
                        </div>
                    </form>
                </td>
            </tr>
        }
</table>

这是表单重定向到的控制器。

[HttpPost]
    [Authorize(Roles = "ADM")]
    public ActionResult UpdateDetails(Guid id, int prodqty)
    {
        BusinessLayer.Orders blorder = new BusinessLayer.Orders();
        CommonLayer.ORDERDETAIL orderdetail = blorder.GetOrderDetailByDetailId(id);
        blorder.UpdateOrderDetails(orderdetail, prodqty);
        return RedirectToAction("ViewOrder");
    }

这是用于实际更新股票的代码。

public void UpdateOrderDetails(CommonLayer.ORDERDETAIL orderdetail, int prodqty)
    {
            CommonLayer.ORDERDETAIL orderDetails = this.GetOrderDetail(orderdetail.OrderDetailsOrderId);
            CommonLayer.ORDERDETAIL od = new CommonLayer.ORDERDETAIL();
            DataLayer.DAProducts daprod = new DataLayer.DAProducts(this.Entities);
            CommonLayer.PRODUCT product = daprod.GetProduct(orderDetails.OrderDetailsProductId);
            od.OrderDetailsProductId = orderDetails.OrderDetailsProductId;
            od.OrderDetailsId = orderDetails.OrderDetailsId;
            od.OrderDetailsOrderId = orderDetails.OrderDetailsOrderId;
            od.ProductVATRate = orderDetails.ProductVATRate;
            od.ProductPrice = orderDetails.ProductPrice;
            od.ProductQuantity = prodqty;
            if (od.ProductQuantity <= product.ProductQuantity)
            {
                if (od.ProductQuantity > orderDetails.ProductQuantity)
                {
                    product.ProductQuantity -= (od.ProductQuantity - orderDetails.ProductQuantity);
                    daprod.UpdateProduct(product);
                    this.Entities.Entry(orderDetails).CurrentValues.SetValues(od);
                    this.Entities.SaveChanges();
                }
                else if (od.ProductQuantity < orderDetails.ProductQuantity)
                {
                    product.ProductQuantity += (orderDetails.ProductQuantity - od.ProductQuantity);
                    daprod.UpdateProduct(product);
                    this.Entities.Entry(orderDetails).CurrentValues.SetValues(od);
                    this.Entities.SaveChanges();
                }
            }
        else
        {
            throw new Exception("Stock is too low");
        }
    }

这就是显示错误的地方,this.Entities.SaveChanges();

public void UpdateProduct(CommonLayer.PRODUCT product)
    {
        CommonLayer.PRODUCT ExistingProduct = this.GetProduct(product.ProductId);
        this.Entities.Entry(ExistingProduct).CurrentValues.SetValues(product);
        this.Entities.SaveChanges();
    }

如何解决问题?

错误:System.Data.SqlClient.SqlException:不允许新事务,因为会话中正在运行其他线程

哦。我认为您过多地重复使用您的实体。尝试为您使用的每个事务初始化新的上下文...执行此操作(再次,从UpdateProduct函数中删除SaveChanges,以便您只调用SaveChanges一次...在if-else-if块之前尝试此操作

using(var context = new CommonLayer.DBModelEntities()){
 if (od.ProductQuantity > orderDetails.ProductQuantity)
 {
   product.ProductQuantity -= (od.ProductQuantity - orderDetails.ProductQuantity);
   daprod.UpdateProduct(product, context);
   context.Entry(orderDetails).CurrentValues.SetValues(od);
 }
 else if (od.ProductQuantity < orderDetails.ProductQuantity)
 {
    product.ProductQuantity += (orderDetails.ProductQuantity - od.ProductQuantity);
    daprod.UpdateProduct(product, context);
    context.Entry(orderDetails).CurrentValues.SetValues(od);
 }
 context.SaveChanges();
}

这样,您还应该更改 UpdateProduct 函数以接收您正在使用的当前数据库上下文

public void UpdateProduct(CommonLayer.PRODUCT product, CommonLayer.DBModelEntities context)
{
  CommonLayer.PRODUCT ExistingProduct = this.GetProduct(product.ProductId);
  context.Entry(ExistingProduct).CurrentValues.SetValues(product);
}

一个好的做法是在控制器中放入开始、保存/回滚事务,以避免SaveChanges调用的多个实例,这就是您在核心函数中所做的 UpdateProductUpdateOrderDetails 触发线程异常

试试这个,删除所有现有的SaveChanges调用你的核心功能UpdateProductUpdateOrderDetails,并将它们放在你的控制器中

[HttpPost]
[Authorize(Roles = "ADM")]
public ActionResult UpdateDetails(Guid id, int prodqty)
{
  // Entities.BeginTransaction here;
  BusinessLayer.Orders blorder = new BusinessLayer.Orders();
  CommonLayer.ORDERDETAIL orderdetail = blorder.GetOrderDetailByDetailId(id);
  blorder.UpdateOrderDetails(orderdetail, prodqty);
  /*Now, check if your data can be Saved by triggering SaveChanges()
   if(Entities.SaveChanges)
  {
    Entities.Commit
  }else
  {
    Entities.Rollback
  } */
  return RedirectToAction("ViewOrder");
}

在这里您可以看到您可以检测记录是否正确保存,在这种情况下您可以将其提交到数据库,否则您可以简单地回滚事务

所有这些作为注释的代码段都可以根据您声明实体的方式而有所不同,但这应该有助于解决您的问题,同时遵循在 MVC 中使用事务的良好做法