при вызове метода из запроса linq выдается сообщение «Вторая операция началась в этом контексте до завершения предыдущей ...» - PullRequest
1 голос
/ 06 мая 2020

Учитывая этот пример псевдокода:

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, не получая никаких ошибок?

Ответы [ 2 ]

0 голосов
/ 07 мая 2020

Это проблема, связанная с 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
              };
0 голосов
/ 06 мая 2020

Я предполагаю, что вы используете EF. Мое предположение / объяснение будет следующим: ваш IQueryable, который вы создаете через LINQ, компилируется через деревья выражений в SQL. EF не знает, как преобразовать вас GetCode в SQL, и он обрабатывается так, как позволяет вызывать его last в вашем запросе, поэтому он может просто оценить его и попытаться сделать запрос к БД, и он видит, что в вашем контексте уже запущена операция (которая генерирует первый SQL). Но во втором случае он может полностью перевести ваш запрос в SQL и сделать один вызов базы данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...