Последовательность метода LINQ любой важности?

Просто интересно, имеет ли значение, в какой последовательности добавляются методы LINQ?

Eg.

using(MyDataContext context = new MyDataContext())
{
   var user = context.Users
                     .Where(u => u.UserName.StartsWith("t"))
                     .OrderByDescending(u => u.CreatedDate)
                     .FirstOrDefault();
}

и это полностью то же самое?

using(MyDataContext context = new MyDataContext())
{
   var user = context.Users
                     .OrderByDescending(u => u.CreatedDate)
                     .Where(u => u.UserName.StartsWith("t"))
                     .FirstOrDefault();
}

Конечно, я могу тестировать все методы один за другим, но я хотел бы получить общее представление о логике.

Итак:

  • Помимо методов, таких как FirstOrDefault(), ToList() и других методов, которые действительно запускают выполнение, важно ли иметь какой-то порядок в инструкции LINQ?

Еще раз спасибо!

Ответ 1

В LINQ to SQL я ожидаю, что эти два запроса будут одинаковыми - они должны получить тот же план запроса, по крайней мере, даже если не тот же SQL.

В LINQ to Objects они будут вести себя по-разному. Представьте, что у вас миллион пользователей, но только у двух из них были имена пользователей, начинающиеся с "t". в первой форме вы будете фильтровать, а затем сортировать этих двух пользователей... во второй форме нужно будет отсортировать все до начала фильтрации.

Конечно, есть и другие ситуации, когда дело касается заказа - в частности, если у вас есть Select на полпути вниз, а затем предложение Where, тогда вы будете фильтровать разные вещи. Представьте себе следующее:

var query = Enumerable.Range(-20, 30)
                      .Select(x => -x)
                      .Where(x => x > 5);

против

var query = Enumerable.Range(-20, 30)
                      .Where(x => x > 5)
                      .Select(x => -x);

В первом примере результаты будут "20, 19, 18,... 6", тогда как во втором запросе результаты будут "-6, -7, -8, -9, -10". Очень разные!

Ответ 2

Это зависит от того, какой поставщик LINQ вы используете. В случае LINQ to SQL дерево выражений будет анализироваться до одного и того же базового SQL-запроса в любом случае. Однако с менее разумным поставщиком вы можете обнаружить, что выполнение .Where() сначала было бы более эффективным, поскольку оно будет фильтровать ваши объекты перед их сортировкой, что может иметь большое значение для большого количества объектов.

Ответ 3

Я не уверен на 100%, но я думаю, что второй медленнее, так как вы сортируете по большему набору данных. Если вы сначала фильтруете, вы удалите некоторые элементы, что ускорит сортировку. Однако результат должен быть одинаков.

EDIT:. Поскольку это выглядит как linq-to-sql (если вы не используете другого провайдера linq), он должен сводиться к тому же самому запросу, который выполняется в этом примере. Но есть ситуации, когда упорядочение имеет значение и в linq-to-sql (см. Пример Jon). Однако единственный способ быть на 100% уверенным - использовать профилировщик для исследования сгенерированного SQL-запроса (но в этом примере я не думаю, что есть какая-либо разница).

Ответ 4

В общем, да, это имеет значение. Вы можете получить различную производительность и/или разные результаты.

В вашем конкретном примере заказ не изменит результат. Для большинства поставщиков, таких как LINQ to SQL и LINQ to Entities, это тоже не будет иметь никакого значения - будет создан тот же SQL.

Для других поставщиков другой порядок может изменять характеристики производительности, но как это зависит от конкретного поставщика. Например, я не думаю, что LINQ to Objects будет иметь одинаковую производительность для обоих запросов.

Ответ 5

Как использовать Sql Profiler? Это даст правильный ответ.

Ответ 6

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

В простом словаре провайдеры LINQ - это просто переводчики, поэтому вы должны задать этот вопрос у создателя поставщика LINQ, который вы используете сейчас.

Ответ 7

У него могут быть проблемы с производительностью. В вашем случае первый пример будет лучшим, потому что на втором вы сначала отсортируете весь список перед фильтрацией. Вы даже сортируете все, что вам не нужно, а затем удаляете ненужные части. Сначала вы удаляете все, что вам не нужно, тогда вы сортируете подмножество, которое (вероятно) будет намного меньше.

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