You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET MVC C#中保存记录后批量更新同ProductID的Qty_Available字段

解决EF中"New transaction not allowed because there are other threads running in the session"错误

问题原因

你这段代码的核心问题有两个:

  • 直接遍历EF的IQueryable延迟加载结果(db.ProductOrders.Where(...)未立即执行查询),同时在循环内调用SaveChanges(),导致DbContext会话中同时存在查询线程和修改操作,触发事务冲突。
  • 每次循环都调用SaveChanges(),不仅效率极低,还会加剧线程冲突的概率。

修正方案

  1. 先将需要修改的记录一次性加载到内存(用ToList()触发立即查询),避免延迟加载占用会话。
  2. 批量修改所有符合条件的记录字段。
  3. 只调用**一次SaveChanges()**完成所有更新。

修正后的代码

// 获取新保存的订单记录
var productOrder = db.ProductOrders.Find(id);
if (productOrder == null)
{
    // 处理记录不存在的情况,比如抛出异常或返回错误提示
    return;
}

// 将所有同ProductID的记录加载到内存,避免延迟加载的会话冲突
var sameProductOrders = db.ProductOrders.Where(x => x.ProductID == productOrder.ProductID).ToList();

// 批量更新Qty_Available字段
foreach (var item in sameProductOrders)
{
    item.Qty_Available = productOrder.Qty_Available;
    db.Entry(item).State = EntityState.Modified;
}

// 一次性提交所有修改
db.SaveChanges();

进阶优化(EF Core 3.0+)

如果使用EF Core,推荐直接用ExecuteUpdate做数据库层面的批量更新,无需加载所有实体,性能更优:

var productOrder = db.ProductOrders.Find(id);
if (productOrder == null)
{
    return;
}

// 直接在数据库执行批量更新,跳过实体加载步骤
db.ProductOrders
    .Where(x => x.ProductID == productOrder.ProductID)
    .ExecuteUpdate(setters => setters.SetProperty(x => x.Qty_Available, productOrder.Qty_Available));

额外注意事项

  • 确保id对应的记录已成功保存到数据库(你提到是保存新记录后获取,此条件已满足)。
  • 若业务存在高并发场景,建议添加事务处理避免数据不一致:
using (var transaction = db.Database.BeginTransaction())
{
    try
    {
        // 执行上述更新逻辑
        db.SaveChanges();
        transaction.Commit();
    }
    catch (Exception)
    {
        transaction.Rollback();
        throw;
    }
}

内容的提问来源于stack exchange,提问作者Kip M.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 09:01:03