2016-06-21 4 views
1

Я знаю, что запросы Entity Framework не могут содержать массивы. Например, это будет терпеть неудачу:Почему мы не можем использовать массивы в запросах Entity Framework?

var myRow = DbContext.myTable.Single(d => d.Property1 == myArray[0].Property1); 

Но если я задаю этот элемент в переменную первой, как это:

var property1 = myArray[0].Property1; 
var myRow = DbContext.myTable.Single(d => d.Property1 == property1); 

Затем он работает. Почему компилятор не может сделать это для нас? Он уже делает оптимизацию и дает нам ярлыки через синтаксический сахар во многих других обстоятельствах. Есть ли источник неоднозначности, который мешает компилятору копировать элемент массива во временную переменную в фоновом режиме? Или какая-то другая причина?

+0

Это не ограничение компилятора C#, а поставщик Linq to Entities. –

+1

Потому что в вашей второй части кода вы работаете с постоянным значением, которое, в свою очередь, может быть частью выражения. Ваш linq в первой части кода не может быть преобразован в выражение. –

+0

Существует много похожих (не совсем повторяющихся) обсуждений почти каждого конкретного метода/свойства, которое не переводится на SQL поставщиками LINQ-to-EF/LINQ-to-SQL. То есть http://stackoverflow.com/questions/3360772/linq-contains-case-insensitive имеет хорошие ссылки на другие обсуждения. –

ответ

3

Linq-to-objects может справиться с этим просто отлично - это linq-to-EF (или Linq-to-SQL), который попытается преобразовать выражение в SQL. Помещение значения в переменную сообщает провайдеру, что вы хотите использовать это значение, а не оценивать выражение.

Почему компилятор не может это сделать для нас?

Поскольку компилятор не был запрограммирован для различения выражений, которые должны быть переведены на SQL, и тех, которые должны быть оценены до компиляции запроса.

Linq запросы используют отложенное выполнение, а это означает, что запрос не является на самом деле выполняется, пока вы не попросите результаты. До тех пор это просто запрос, состоящий из отдельных выражений, которые составляют фильтры, проекции, группировки, агрегации и т. Д. Когда он оценивает выражение d => d.Property1 == myArray[0].Property1, не оценивает выражение в это время, поэтому, когда провайдер добирается до него , он пытается преобразовать его в SQL, чего он не может сделать.

+0

И поскольку компилятор не может различать Дерево выражений, которое будет выполняться синхронно (таким образом, возможно преобразование индексированного доступа к его результату) по сравнению с асинхронным (когда элемент с заданным индексом может меняться несколько раз до того, как будет оценено выражение). –

Смежные вопросы