2011-01-26 6 views
0

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

IEnumerable<string> outerQuery = names.Where (n => n.Length == names 
        .OrderBy(n2 => n2.Length).Select(n2 => n2.Length).First()); 

Я ожидаю, что приведенный выше запрос будет работать так же, как показано ниже, т.е. как если бы не был подзапрос.

int val = names.OrderBy(n2 => n2.Length).Select(n2 => n2.Length).First(); 

IEnumerable<string> outerQuery = names.Where (n => n.Length == val); 

Этот пример был взят из Джозефа и Бен Albahari-х С # 4.0 в двух словах (CHP 8 Р331/332) и моя путаница проистекает из прилагаемой диаграммы, по-видимому, показывают, что подзапрос оценивается каждый раз, когда наружный запрос выполняет итерации через элементы имен.

Может ли кто-нибудь уточнить, как LINQ работает в этой настройке? Любая помощь будет оценена!

+0

Hi Rionmonster, подзапросом будут имена .OrderBy (n2 => n2.Length). Выберите (n2 => n2.Length) .First() – Simon

ответ

1

В следующем примере я буду прав, сказав, что внутренний запрос выполняется немедленно?

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

ИЗМЕНИТЬ: как указал Люкх, это относится только к Linq к объектам. Другие провайдеры Linq (Linq to SQL, Entity Framework ...) могут быть в состоянии оптимизировать это автоматически

+2

Это относится к LINQ-to-Objects - и I ' уверен, что это касается этого вопроса, но стоит также отметить, что любая из реализаций LINQ на основе IQueryable может оптимизироваться практически так, как им нравится, когда они переводят дерево выражений, так что это может быть неверно для LINQ-to-SQL и т. д. – LukeH

+0

@ LukeH, вы правы, конечно ... У меня был Linq для объектов в памяти –

+0

Спасибо за быстрый ответ Thomas, да, я говорил о местной коллекции (в данном случае строки). Я предполагаю, что я действительно не понимаю, почему он не оценивается сразу, поскольку это было бы само по себе. Ты знаешь почему? – Simon

0

Что такое names? Если это коллекция (и вы используете LINQ to Objects), тогда для каждого внешнего элемента запроса будет выполняться «подзапрос». Если это объект запроса, результат будет зависеть от фактического IQueryable.Provider. Например, для LINQ to SQL вы получите SQL-запрос со скалярным подзапросом. И в большинстве случаев подзапрос фактически будет выполняться только один раз.

+0

Привет, oryol, это будет коллекция. Если такой запрос обычно будет немедленно оценен, почему это будет отличаться в подзапросе? – Simon

+0

_Where_ метод для LINQ to Objects - это просто foreach. Поэтому для каждого внешнего элемента коллекции будет выполняться внутренний делегат. Он содержит еще один запрос LINQ (другой цикл, а также OrderBy - даже ~ 2 цикла). – oryol

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