Ответ на ваш вопрос будет действительно многословным, поскольку он соответствует некоторым другим изменениям, произошедшим в EF Core 3.0;Итак, давайте просто рассмотрим небольшую его часть.
Как вы упомянули в своем вопросе, у Microsoft есть несколько запутанное описание изменений в версии 3.0 в этом посте .
Первая часть вышеприведенного сообщения: « LINQ-запросы больше не оцениваются на клиенте ». Там написано, что раньше разработчики писали запросы, состоящие из двух частей;Одна часть - это запрос к базе данных, а другая - выражение, известное только для клиентского кода. В этой ситуации client evaluation of potentially expensive expressions only triggered a warning
. Но в новой версии ядро EF позволяет только последнему вызову Select () быть оцененным на клиенте и генерирует исключение, когда есть выражения, которые нельзя преобразовать ни в SQL, ни в параметр.
Чтобы очистить этоВ заключение рассмотрим пример, описанный Диего Вегой в его сообщении в блоге EF Core 3.0 .
Явное переключение на оценку клиента : ЕслиВаш запрос фильтрует данные на основе выражения, которое не может быть переведено в SQL. Возможно, вам придется явно переключиться на оценку клиента, вставив вызов либо в AsEnumerable (), AsAsyncEnumerable (), ToList (), либо ToListAsync () в серединезапрос. Например, следующий запрос больше не будет работать в EF Core 3.0, поскольку один из предикатов в предложении where требует оценки клиента:
var specialCustomers = context.Customers
.Where(c => c.Name.StartsWith(n) && IsSpecialCustomer(c));
Но если вы знаете, что разумнообрабатывая часть фильтра на клиенте, вы можете переписать запрос следующим образом:
var specialCustomers = context.Customers
.Where(c => c.Name.StartsWith(n))
.AsEnumerable() // Start using LINQ to Objects (switch to client evaluation)
.Where(c => IsSpecialCustomer(c));
В приведенном выше примере IsSpecialCustomer(c)
- это метод, который не может быть преобразован в SQL, поскольку это метод C #, которыйэто доступно только в коде клиента. Таким образом, разработчики должны либо переписать запрос в форме, которую можно перевести, либо выполнить запрос к базе данных, а затем оценить результаты базы данных для клиента, используя .AsEnumerable()
, а затем можно отфильтровать результаты на основе возвращенного значения IsSpecialCustomer(c)
. Вот почему вы все еще можете получить доступ к AsEnumerable()
в своем коде.
Теперь давайте посмотрим, почему метод FirstOrDefaultAsync()
недоступен?
Ну, естьдве причины, которые вызывают эту ситуацию.
Я ответил на первую причину раньше: код для обнаружения нескомпозиционного SQL был удален в версии 3.0.
И вторая: конвейер запросов делаетне понимаю асинхронные операторы с запросом в дереве выражений (например, когда вы пытаетесь получить к нему доступ в EF.CompileQuery()
).
В общем, есть пара интересных сообщений, которые выможно прочитать:
40 критических изменений в ядре ef core 3
Объявление структуры ядра ядра 3.0, предварительный просмотр 9 и структуры объекта 6.3, предварительный просмотр 9
Проблемы с ядром EF на github