【问题标题】:New transaction is not allowed because there are other threads running in the session LINQ To Entity [duplicate]不允许新事务,因为会话 LINQ To 实体中正在运行其他线程 [重复]
【发布时间】:2012-04-23 04:50:04
【问题描述】:

关于为什么这可能会破坏的任何想法?

foreach (var p in pp)
{
    ProjectFiles projectFile = (ProjectFiles)p;
    projectFile.Status = Constants.ProjectFiles_ERROR;
    projectFile.DateLastUpdated = DateTime.Now;
    context.SaveChanges();
}

我了解到该问题的解决方法是在 foreach 循环之前一次性检索结果。

但我没有这样做吗? “pp”是我的情况的结果集合

【问题讨论】:

  • pp 是 linq 查询的结果吗?如果是这样,您可能需要在运行循环之前对其执行ToList() 以断开其与数据库的连接。
  • 是的。好的,我会试试谢谢
  • 在循环外调用保存更改
  • 这里只是一个小指针。建议的修复可能通过阻止 EF 在每次保存时不断启动新事务来起作用。但是,它指出了 EF 中的一个问题。这里的逻辑可能不对。您应该在循环保存之前启动事务,然后全部提交,或者最后回滚。除非这当然不是我们想要的逻辑。

标签: c# linq linq-to-entities


【解决方案1】:

pp 变量不是对象的集合,它是一个可以返回对象的枚举器。使用枚举器时,源必须保持打开状态。

使用ToList方法将枚举数实现为集合。这将从枚举器中读取所有项目并关闭与源的连接,以便您可以将连接用于其他事情。

foreach (var p in pp.ToList())

【讨论】:

  • 上帝保佑你@Guffa !!! +1
  • 太棒了!它也适用于 pp.ToArray()
  • Ricardo,只要不是 IQueryable 就可以工作
  • @Guffa 我遇到了完全相同的问题,这个简单的添加对我有用!谢谢!
  • 需要注意的是,这个问题并不是实体框架特有的。它与底层的 SQL Server SqlConnection 对象有关。显然,在这种情况下,实体框架认为适合为每次保存启动事务。这是一个糟糕的想法,也是不使用实体框架的一个论据。我的猜测是代码应该提交所有更改,或者回滚它们。此代码应包装在单个事务中以实现此目的。 EF 正在隐藏事务处理。
【解决方案2】:

解决此问题的一种方法是在迭代之前对您的集合调用 .ToList()

当您使用它时,请在循环退出后仅调用一次 context.SaveChanges() 以加快代码速度。

【讨论】:

  • 根据已接受的解决方案的断言以及在此问题顶部链接的另一个已回答问题中提供的断言,此声明似乎并未描述真实情况。似乎更多的是尝试在迭代完成之前进行更改保存,而不是使用多个连接
  • 是的,没有多个连接正在进行。它与从连接中读取同时尝试在其上写入有关。
  • 但是如果我要迭代一百万个项目,我无法将它们全部加载到内存中。必须有一种方法可以在进行更新的同时进行迭代。
  • ORM 不是更新数百万条记录的方法。它们用于填充复杂的对象,可能还有一些 CRUD,但是应该直接在数据库上执行批量操作,或者至少通过专门用于批量操作的库来执行批量操作。
  • 如果您可以通过存储过程或计划作业执行批量操作,那么理想情况下您应该这样做。
猜你喜欢
  • 2017-03-27
  • 1970-01-01
  • 2016-07-07
  • 2012-09-07
  • 1970-01-01
  • 2017-06-26
  • 1970-01-01
相关资源
最近更新 更多