int[] ids1 = { 1, 2, 3 };
int[] ids2 = { 1, 5, 6 };
var result = from a in ids1
where a == ids2.First()
select a;
foreach (var item in result) ; //ok
var employees = from c in context.Employees.
where c.EmployeeID == ids1.First()
select c;
foreach (var item in employees); // NotSupportedException
При попытке вызвать ids1.First
в запросе Linq-to-Entities, я получаю исключение
System.NotSupportedException: Метод 'First' может быть использован только в качестве конечной операции запроса. Рассмотрите возможность использования метода 'FirstOrDefault' в этом экземпляре вместо этого.
a) Я не понимаю, почему First
может использоваться только как финальная операция запроса, так как в нашем примере First
вызывается на IEnumerable<>
( ids1.First()
), а не на IQueryable<>
. Другими словами, First
вызывается в запросе Linq-to-Objects, а не в запросе Linq-to-Entities?!
б) В любом случае, почему First
должен использоваться как заключительная операция запроса, а FirstOrDefault
не должен быть заключительной операцией запроса?
Спасибо
ОТВЕТ:
Что касается разницы между First() и FirstOrDefault() - я не знаю. знаю. Вы пробовали, и работает ли это?
Да, работает
Нет, First() вызывается в запросе LINQ to Entities. Ваше где будет преобразовано в: Where(c => c.EmployeeID == ids1.First())
a) Теперь я немного запутался. Я понимаю, что ids1.First
по сути вызывается внутри запроса Linq-to-Entities, но факт остается фактом: First
вызывается на IEnumerable<>
, и как таковой First
вызывается внутри запроса Linq-to-Objects, а этот запрос Linq-to-Object в свою очередь вызывается внутри запроса Linq-To-entities - по крайней мере так я это понимаю?!
Или вы подразумеваете, что First
как-то вызывается на IQeryable<>
?
б) Я понимаю, что (c => c.EmployeeID == ids1.First())
будет преобразован в дерево выражений, но почему ids1.First()
не выполняется до преобразования?
c) В любом случае, когда преобразование в дерево выражений произойдет, я предполагаю, что когда sql-провайдер получит дерево выражений нашего where
предложения и попытается преобразовать его в Sql команду, у этого Sql-провайдера не хватит "мощности" выполнить ids1.First
, чтобы получить результат обратно (который он затем поместит в Sql запрос), и отсюда исключение?!
ВТОРОЙ ОТВЕТ:
a) Я все еще не понимаю, почему ids1.First
не выполняется до преобразования в дерево выражений?! А именно, при следующем пункте
Where(c => c.EmployeeID == 2+3)
выражение 2+3
выполняется до того, как этот пункт Where преобразуется в дерево выражений! А ids.First
- это тоже своего рода выражение, так что я ожидал бы аналогичного поведения!
b) Извините за повторение, но меня очень беспокоит, действительно ли мое предположение - что
First
вызывается внутри запроса Linq-to-Objects, а этот запрос Linq-to-Object в свою очередь вызывается внутри запроса Linq-To-entities - верно?!
c) Возможно, я неправильно понял ваш пост, но вы подразумеваете, что большинство других операторов Linq-to-Object могут быть вызваны на IEnumerable<> E
, даже если E
содержится в запросе Linq-to-Entities ?