C# 从linq查询调用方法会抛出;在上一个操作完成之前,在此上下文上启动了第二个操作;

C# 从linq查询调用方法会抛出;在上一个操作完成之前,在此上下文上启动了第二个操作;,c#,linq,asp.net-core,C#,Linq,Asp.net Core,给定此示例伪代码: var student = from s in ctx.Students where s.StudentName == "Bill" let code = GetCode(s.Id) select new { Name = s.StudentName, Code = code.Code

给定此示例伪代码:

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方法而不出现任何错误?

我假设您使用的是EF。我的假设/解释是:通过LINQ创建的
IQueryable
将通过编译成SQL。EF不知道如何将您的
GetCode
转换为SQL,它被作为查询中的
last
语句进行处理,因此它可以对其求值并尝试对DB进行查询,它发现您的上下文中已经开始了一个操作(正在生成第一个SQL)。但在第二种情况下,它可以将您的查询完全转换为SQL并对db进行一次调用。

我假设您使用的是EF。我的假设/解释是:通过LINQ创建的
IQueryable
将通过编译成SQL。EF不知道如何将您的
GetCode
转换为SQL,它被作为查询中的
last
语句进行处理,因此它可以对其求值并尝试对DB进行查询,它发现您的上下文中已经开始了一个操作(正在生成第一个SQL)。但在第二种情况下,它可以将您的查询完全转换为SQL并对db进行一次调用。

这是一个与SQL相关的问题。where后面的条件在服务器上运行,并且服务器端没有定义
GetCode
方法,因此服务器端无法识别GetCode方法并导致错误

请参阅

解决方案是在客户机上执行整个SQL语句
,并将
ctx.Students
转换为一个集合表单
ctx.Students.ToList()


这是一个与之相关的问题。where后面的条件在服务器上运行,并且服务器端没有定义
GetCode
方法,因此服务器端无法识别GetCode方法并导致错误

请参阅

解决方案是在客户机上执行整个SQL语句
,并将
ctx.Students
转换为一个集合表单
ctx.Students.ToList()


扔掉
GetCode
并使用
join
更有效。更改方法签名:
code-GetCode(YourContext-ctx,int-id)
@Dennis这是一个示例代码-我的查询更多complex@AlexanderPetrov我试过了,结果也一样error@user441365:查询复杂性如何阻止您使用联接?第二个示例有效,但它会导致子查询。从数据库的角度来看,这是非常低效的。丢弃
GetCode
并使用
join
更有效。更改方法签名:
code-GetCode(YourContext-ctx,int-id)
@Dennis这是一个示例代码-我的查询更多complex@AlexanderPetrov我试过了,结果也一样error@user441365:查询复杂性如何阻止您使用联接?第二个示例有效,但它会导致子查询。从数据库的角度来看,这是非常低效的。谢谢你的解释-有什么办法可以让我调用函数吗?@user441365无法从我的头脑中找到一个优雅的解决方案,但是你可以尝试实现一个令人讨厌的方法,比如感谢你的解释——有没有办法让我调用一个函数?@user441365无法从我的头脑中找到一个优雅的解决方案,但是你可以尝试实现一个令人讨厌的方法,比如
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
              };