【问题标题】:calling a method from a linq query throws "A second operation started on this context before a previous operation completed..."从 linq 查询调用方法会引发“在前一个操作完成之前在此上下文上启动的第二个操作......”
【发布时间】:2020-05-06 11:32:05
【问题描述】:

鉴于此示例伪代码:

var student = from s in ctx.Students
              where s.StudentName == "Bill"
              let code = GetCode(s.Id)
              select new
              {
                 Name = s.StudentName,
                 Code = code.Code
              };

private Code GetCode(int id)
{
     return ctx.Codes.FirstOrDefault(x => x.Id == id);
}

我收到此错误消息:

"第二个操作在前一个上下文之前开始 操作完成。这通常是由不同的线程使用 DbContext 的相同实例,但实例成员不是 保证是线程安全的。这也可能是由嵌套引起的 在客户端上评估的查询,如果是这种情况,请重写 查询避免嵌套调用。”

但如果我在 let 子句中明确地编写查询,它就可以正常工作:

var student = from s in ctx.Students
              where s.StudentName == "Bill"
              let ctx.Codes.FirstOrDefault(x => x.Id == s.Id)
              select new
              {
                 Name = s.StudentName,
                 Code = code.Code
              };

有没有一种方法可以调用 GetCode 方法而不会出现任何错误?

【问题讨论】:

  • 扔掉GetCode而使用join效率更高。
  • 更改方法签名:Code GetCode(YourContext ctx, int id).
  • @Dennis 这是一个示例代码 - 我的查询要复杂得多
  • @AlexanderPetrov 我试过了,我得到了同样的错误
  • @user441365:查询复杂性如何阻止您使用联接?您的第二个示例有效,但会导致子查询。从数据库的角度来看,这是非常低效的。

标签: c# linq asp.net-core


【解决方案1】:

我假设您使用的是 EF。我的假设/解释是下一个:您通过 LINQ 创建的 IQueryable 通过 expression trees 编译成 SQL。 EF 不知道如何将您的 GetCode 转换为 SQL,它的处理方式是让我们在您的查询中将其称为 last 语句,因此它可以对其进行评估并尝试对数据库进行查询,它会看到存在已经在您的上下文(正在生成第一个 SQL)上启动了一个操作。但在第二种情况下,它可以将您的查询完全转换为 SQL 并调用数据库。

【讨论】:

  • 感谢您的解释 - 有什么办法可以让我调用函数吗?
  • @user441365 无法从我的脑海中找到一个优雅的解决方案,但你可以尝试实现一个像this 这样的讨厌的解决方案
【解决方案2】:

这是与client evaluation 相关的问题。 where后面的条件是在服务端运行,服务端没有定义GetCode方法,所以服务端无法识别GetCode方法,导致报错。

请参考this

解决方法是执行整个SQL语句on the client,将ctx.Students转换成集合形式ctx.Students.ToList()

var student = from s in ctx.Students.ToList()
              where s.StudentName == "Bill"
              let code = GetCode(s.Id)
              select new
              {
                 Name = s.StudentName,
                 Code = code.Code
              };

【讨论】:

    猜你喜欢
    • 2019-12-17
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    • 2021-10-22
    相关资源
    最近更新 更多