СДЕЛАЙТЕ СВОИ УРОКИ ЕЩЁ ЭФФЕКТИВНЕЕ, А ЖИЗНЬ СВОБОДНЕЕ

Благодаря готовым учебным материалам для работы в классе и дистанционно

Скидки до 50 % на комплекты
только до

Готовые ключевые этапы урока всегда будут у вас под рукой

Организационный момент

Проверка знаний

Объяснение материала

Закрепление изученного

Итоги урока

Лекция Основы LINQ

Категория: Информатика

Нажмите, чтобы узнать подробности

Просмотр содержимого документа
«Лекция Основы LINQ»

Основы LINQ

Основы LINQ

 LINQ (Language-Integrated Query) представляет простой и удобный язык запросов к источнику данных. В качестве источника данных может выступать объект, реализующий интерфейс IEnumerable (например, стандартные коллекции, массивы), набор данных DataSet, документ XML. Но вне зависимости от типа источника LINQ позволяет применить ко всем один и тот же подход для выборки данных.
  • LINQ (Language-Integrated Query) представляет простой и удобный язык запросов к источнику данных. В качестве источника данных может выступать объект, реализующий интерфейс IEnumerable (например, стандартные коллекции, массивы), набор данных DataSet, документ XML. Но вне зависимости от типа источника LINQ позволяет применить ко всем один и тот же подход для выборки данных.
  Существует несколько разновидностей LINQ: LINQ to Objects: применяется для работы с массивами и коллекциями LINQ to Entities: используется при обращении к базам данных через технологию Entity Framework LINQ to Sql: технология доступа к данным в MS SQL Server LINQ to XML: применяется при работе с файлами XML LINQ to DataSet: применяется при работе с объектом DataSet Parallel LINQ (PLINQ): используется для выполнения параллельных запросов

Существует несколько разновидностей LINQ:

  • LINQ to Objects: применяется для работы с массивами и коллекциями
  • LINQ to Entities: используется при обращении к базам данных через технологию Entity Framework
  • LINQ to Sql: технология доступа к данным в MS SQL Server
  • LINQ to XML: применяется при работе с файлами XML
  • LINQ to DataSet: применяется при работе с объектом DataSet
  • Parallel LINQ (PLINQ): используется для выполнения параллельных запросов
 Речь пойдет прежде всего о LINQ to Objects, но в последующих материалах также будут затронуты и другие разновидности LINQ.
  • Речь пойдет прежде всего о LINQ to Objects, но в последующих материалах также будут затронуты и другие разновидности LINQ.
 В чем же удобство LINQ? Посмотрим на простейшем примере. Выберем из массива строки, начинающиеся на определенную букву и отсортируем полученный список:
  • В чем же удобство LINQ? Посмотрим на простейшем примере. Выберем из массива строки, начинающиеся на определенную букву и отсортируем полученный список:
  Теперь проведем те же действия с помощью LINQ:

Теперь проведем те же действия с помощью LINQ:

Чтобы использовать функциональность LINQ, убедимся, что в файле подключено пространство имен System.LINQ. Итак, код стал меньше и проще. В принципе все выражение можно было бы записать в одну строку: var selectedTeams = from t in teams where t.ToUpper().StartsWith(
  • Чтобы использовать функциональность LINQ, убедимся, что в файле подключено пространство имен System.LINQ.
  • Итак, код стал меньше и проще. В принципе все выражение можно было бы записать в одну строку: var selectedTeams = from t in teams where t.ToUpper().StartsWith("Б") orderby t select t. Но для более понятной логической разбивки было сделано каждое отдельное подвыражение на отдельной строке.
Простейшее определение запроса LINQ выглядит следующим образом:
  • Простейшее определение запроса LINQ выглядит следующим образом:
Итак, что делает этот запрос LINQ? Выражение from t in teams проходит по всем элементам массива teams и определяет каждый элемент как t. Используя переменную t мы можем проводить над ней разные операции.
  • Итак, что делает этот запрос LINQ? Выражение from t in teams проходит по всем элементам массива teams и определяет каждый элемент как t. Используя переменную t мы можем проводить над ней разные операции.
Несмотря на то, что мы не указываем тип переменной t, выражения LINQ являются строго типизированными. То есть среда автоматически распознает, что набор teams состоит из объектов string, поэтому переменная t будет рассматриваться в качестве строки.
  • Несмотря на то, что мы не указываем тип переменной t, выражения LINQ являются строго типизированными. То есть среда автоматически распознает, что набор teams состоит из объектов string, поэтому переменная t будет рассматриваться в качестве строки.
Далее с помощью оператора where проводится фильтрация объектов, и если объект соответствует критерию (в данном случае начальная буква должна быть
  • Далее с помощью оператора where проводится фильтрация объектов, и если объект соответствует критерию (в данном случае начальная буква должна быть "Б"), то этот объект передается дальше.
Оператор orderby упорядочивает по возрастанию, то есть сортирует выбранные объекты. Оператор select передает выбранные значения в результирующую выборку, которая возвращается LINQ-выражением.
  • Оператор orderby упорядочивает по возрастанию, то есть сортирует выбранные объекты.
  • Оператор select передает выбранные значения в результирующую выборку, которая возвращается LINQ-выражением.
В данном случае результатом выражения LINQ является объект IEnumerable. Нередко результирующая выборка определяется с помощью ключевого слова var, тогда компилятор на этапе компиляции сам выводит тип. Преимуществом подобных запросов также является и то, что они интуитивно похожи на запросы языка SQL, хотя и имеют некоторые отличия.
  • В данном случае результатом выражения LINQ является объект IEnumerable. Нередко результирующая выборка определяется с помощью ключевого слова var, тогда компилятор на этапе компиляции сам выводит тип.
  • Преимуществом подобных запросов также является и то, что они интуитивно похожи на запросы языка SQL, хотя и имеют некоторые отличия.
Методы расширения LINQ Кроме стандартного синтаксиса from .. in .. select для создания запроса LINQ мы можем применять специальные методы расширения, которые определены для интерфейса IEnumerable. Как правило, эти методы реализуют ту же функциональность, что и операторы LINQ типа where или orderby.

Методы расширения LINQ

  • Кроме стандартного синтаксиса from .. in .. select для создания запроса LINQ мы можем применять специальные методы расширения, которые определены для интерфейса IEnumerable. Как правило, эти методы реализуют ту же функциональность, что и операторы LINQ типа where или orderby.
Например:

Например:

t.ToUpper().StartsWith("Б")).OrderBy(t = t) будет аналогичен предыдущему. Он состоит из цепочки методов Where и OrderBy. В качестве аргумента эти методы принимают делегат или лямбда-выражение. " width="640"
  • Запрос teams.Where(t=t.ToUpper().StartsWith("Б")).OrderBy(t = t) будет аналогичен предыдущему. Он состоит из цепочки методов Where и OrderBy. В качестве аргумента эти методы принимают делегат или лямбда-выражение.
Не каждый метод расширения имеет аналог среди операторов LINQ, но в этом случае можно сочетать оба подхода. Например, используем стандартный синтаксис linq и метод расширения Count(), возвращающий количество элементов в выборке :
  • Не каждый метод расширения имеет аналог среди операторов LINQ, но в этом случае можно сочетать оба подхода. Например, используем стандартный синтаксис linq и метод расширения Count(), возвращающий количество элементов в выборке :
Список используемых методов расширения LINQ Select: определяет проекцию выбранных значений Where: определяет фильтр выборки OrderBy: упорядочивает элементы по возрастанию OrderByDescending: упорядочивает элементы по убыванию ThenBy: задает дополнительные критерии для упорядочивания элементов возрастанию

Список используемых методов расширения LINQ

  • Select: определяет проекцию выбранных значений
  • Where: определяет фильтр выборки
  • OrderBy: упорядочивает элементы по возрастанию
  • OrderByDescending: упорядочивает элементы по убыванию
  • ThenBy: задает дополнительные критерии для упорядочивания элементов возрастанию
ThenByDescending: задает дополнительные критерии для упорядочивания элементов по убыванию Join: соединяет две коллекции по определенному признаку GroupBy: группирует элементы по ключу ToLookup: группирует элементы по ключу, при этом все элементы добавляются в словарь GroupJoin: выполняет одновременно соединение коллекций и группировку элементов по ключу
  • ThenByDescending: задает дополнительные критерии для упорядочивания элементов по убыванию
  • Join: соединяет две коллекции по определенному признаку
  • GroupBy: группирует элементы по ключу
  • ToLookup: группирует элементы по ключу, при этом все элементы добавляются в словарь
  • GroupJoin: выполняет одновременно соединение коллекций и группировку элементов по ключу
Reverse: располагает элементы в обратном порядке All: определяет, все ли элементы коллекции удовлятворяют определенному условию Any: определяет, удовлетворяет хотя бы один элемент коллекции определенному условию Contains: определяет, содержит ли коллекция определенный элемент Distinct: удаляет дублирующиеся элементы из коллекции Except: возвращает разность двух коллекцию, то есть те элементы, которые создаются только в одной коллекции Union: объединяет две однородные коллекции
  • Reverse: располагает элементы в обратном порядке
  • All: определяет, все ли элементы коллекции удовлятворяют определенному условию
  • Any: определяет, удовлетворяет хотя бы один элемент коллекции определенному условию
  • Contains: определяет, содержит ли коллекция определенный элемент
  • Distinct: удаляет дублирующиеся элементы из коллекции
  • Except: возвращает разность двух коллекцию, то есть те элементы, которые создаются только в одной коллекции
  • Union: объединяет две однородные коллекции
Intersect: возвращает пересечение двух коллекций, то есть те элементы, которые встречаются в обоих коллекциях Count: подсчитывает количество элементов коллекции, которые удовлетворяют определенному условию
  • Intersect: возвращает пересечение двух коллекций, то есть те элементы, которые встречаются в обоих коллекциях
  • Count: подсчитывает количество элементов коллекции, которые удовлетворяют определенному условию
Sum: подсчитывает сумму числовых значений в коллекции Average: подсчитывает cреднее значение числовых значений в коллекции Min: находит минимальное значение Max: находит максимальное значение Take: выбирает определенное количество элементов
  • Sum: подсчитывает сумму числовых значений в коллекции
  • Average: подсчитывает cреднее значение числовых значений в коллекции
  • Min: находит минимальное значение
  • Max: находит максимальное значение
  • Take: выбирает определенное количество элементов
Skip: пропускает определенное количество элементов TakeWhile: возвращает цепочку элементов последовательности, до тех пор, пока условие истинно SkipWhile: пропускает элементы в последовательности, пока они удовлетворяют заданному условию, и затем возвращает оставшиеся элементы Concat: объединяет две коллекции Zip: объединяет две коллекции в соответствии с определенным условием
  • Skip: пропускает определенное количество элементов
  • TakeWhile: возвращает цепочку элементов последовательности, до тех пор, пока условие истинно
  • SkipWhile: пропускает элементы в последовательности, пока они удовлетворяют заданному условию, и затем возвращает оставшиеся элементы
  • Concat: объединяет две коллекции
  • Zip: объединяет две коллекции в соответствии с определенным условием
First: выбирает первый элемент коллекции FirstOrDefault: выбирает первый элемент коллекции или возвращает значение по умолчанию Single: выбирает единственный элемент коллекции, если коллекция содердит больше или меньше одного элемента, то генерируется исключение SingleOrDefault: выбирает первый элемент коллекции или возвращает значение по умолчанию
  • First: выбирает первый элемент коллекции
  • FirstOrDefault: выбирает первый элемент коллекции или возвращает значение по умолчанию
  • Single: выбирает единственный элемент коллекции, если коллекция содердит больше или меньше одного элемента, то генерируется исключение
  • SingleOrDefault: выбирает первый элемент коллекции или возвращает значение по умолчанию
ElementAt: выбирает элемент последовательности по определенному индексу ElementAtOrDefault: выбирает элемент коллекции по определенному индексу или возвращает значение по умолчанию, если индекс вне допустимого диапазона Last: выбирает последний элемент коллекции LastOrDefault: выбирает последний элемент коллекции или возвращает значение по умолчанию
  • ElementAt: выбирает элемент последовательности по определенному индексу
  • ElementAtOrDefault: выбирает элемент коллекции по определенному индексу или возвращает значение по умолчанию, если индекс вне допустимого диапазона
  • Last: выбирает последний элемент коллекции
  • LastOrDefault: выбирает последний элемент коллекции или возвращает значение по умолчанию
Фильтрация Для выбора элементов из некоторого набора по условию используется метод Where. Например, выберем все четные элементы, которые больше 10.

Фильтрация

  • Для выбора элементов из некоторого набора по условию используется метод Where. Например, выберем все четные элементы, которые больше 10.
Фильтрация с помощью операторов LINQ: Здесь используется конструкция from: from i in numbers
  • Фильтрация с помощью операторов LINQ:

Здесь используется конструкция from: from i in numbers

10), то данный элемент попадает в результирующую выборку. " width="640"
  • Тот же запрос с помощью метода расширения:

Если выражение в методе Where для определенного элемента будет равно true (в данном случае выражение i % 2 == 0 && i 10), то данный элемент попадает в результирующую выборку.

Выборка сложных объектов Допустим, у нас есть класс пользователя:

Выборка сложных объектов

  • Допустим, у нас есть класс пользователя:
Создадим набор пользователей и выберем из них тех, которым больше 25 лет:
  • Создадим набор пользователей и выберем из них тех, которым больше 25 лет:
Консольный вывод: Аналогичный запрос с помощью метода расширения Where:

Консольный вывод:

Аналогичный запрос с помощью метода расширения Where:

Сложные фильтры Теперь рассмотрим более сложные фильтры. Например, в классе пользователя есть список языков, которыми владеет пользователь. Что если нам надо отфильтровать пользователей по языку:

Сложные фильтры

  • Теперь рассмотрим более сложные фильтры. Например, в классе пользователя есть список языков, которыми владеет пользователь. Что если нам надо отфильтровать пользователей по языку:
Результат:

Результат:

Для создания аналогичного запроса с помощью методов расширения применяется метод SelectMany:
  • Для создания аналогичного запроса с помощью методов расширения применяется метод SelectMany:
Метод SelectMany() в качестве первого параметра принимает последовательность, которую надо проецировать, а в качестве второго параметра - функцию преобразования, которая применяется к каждому элементу. На выходе она возвращает 8 пар
  • Метод SelectMany() в качестве первого параметра принимает последовательность, которую надо проецировать, а в качестве второго параметра - функцию преобразования, которая применяется к каждому элементу. На выходе она возвращает 8 пар "пользователь - язык" (new { User = u, Lang = l }), к которым потом применяетс фильтр с помощью Where.
Проекция Проекция позволяет спроектировать из текущего типа выборки какой-то другой тип. Для проекции используется оператор select. Допустим, у нас есть набор объектов следующего класса, представляющего пользователя:

Проекция

  • Проекция позволяет спроектировать из текущего типа выборки какой-то другой тип. Для проекции используется оператор select. Допустим, у нас есть набор объектов следующего класса, представляющего пользователя:
Но нам нужен не весь объект, а только его свойство Name:
  • Но нам нужен не весь объект, а только его свойство Name:
Результат выражения LINQ будет представлять набор строк, поскольку выражение select u.Name выбирают в результирующую выборку только значения свойства Name.
  • Результат выражения LINQ будет представлять набор строк, поскольку выражение select u.Name выбирают в результирующую выборку только значения свойства Name.
Аналогично можно создать объекты другого типа, в том числе анонимного:
  • Аналогично можно создать объекты другого типа, в том числе анонимного:
Здесь оператор select создает объект анонимного типа, используя текущий объект User. И теперь результат будет содержать набор объектов данного анонимного типа, в котором определены два свойства: FirstName и DateOfBirth.
  • Здесь оператор select создает объект анонимного типа, используя текущий объект User. И теперь результат будет содержать набор объектов данного анонимного типа, в котором определены два свойства: FirstName и DateOfBirth.
В качестве альтернативы мы могли бы использовать метод расширения Select():
  • В качестве альтернативы мы могли бы использовать метод расширения Select():
Переменые в запросах и оператор let Иногда возникает необходимость произвести в запросах LINQ какие-то дополнительные промежуточные вычисления. Для этих целей мы можем задать в запросах свои переменные с помощью оператора let :

Переменые в запросах и оператор let

  • Иногда возникает необходимость произвести в запросах LINQ какие-то дополнительные промежуточные вычисления. Для этих целей мы можем задать в запросах свои переменные с помощью оператора let :
В данном случае создается переменная name, значение которой равно
  • В данном случае создается переменная name, значение которой равно "Mr. " + u.Name.
  • Возможность определения переменных наверное одно из главных преимуществ операторов LINQ по сравнению с методами расширения.
Выборка из нескольких источников В LINQ можно выбирать объекты не только из одного, но и из большего количества источников: Например, возьмем классы:

Выборка из нескольких источников

  • В LINQ можно выбирать объекты не только из одного, но и из большего количества источников:
  • Например, возьмем классы:
Создадим два разных источника данных и произведем выборку:

Создадим два разных источника данных и произведем выборку:

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

Консольный вывод:

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

Сортировка Для сортировки набора данных по возрастанию используется оператор orderby:

Сортировка

  • Для сортировки набора данных по возрастанию используется оператор orderby:
Оператор orderby принимает критерий сортировки. В данном случае в качестве критерия выступает само число.
  • Оператор orderby принимает критерий сортировки. В данном случае в качестве критерия выступает само число.
Возьмем посложнее пример. Допустим, надо отсортировать выборку сложных объектов. Тогда в качестве критерия мы можем указать свойство класса объекта:
  • Возьмем посложнее пример. Допустим, надо отсортировать выборку сложных объектов. Тогда в качестве критерия мы можем указать свойство класса объекта:
По умолчанию оператор orderby производит сортировку по возрастанию. Однако с помощью ключевых слов ascending (сортировка по возрастанию) и descending (сортировка по убыванию) можно явным образом указать направление сортировки:
  • По умолчанию оператор orderby производит сортировку по возрастанию. Однако с помощью ключевых слов ascending (сортировка по возрастанию) и descending (сортировка по убыванию) можно явным образом указать направление сортировки:
Вместо оператора orderby можно использовать методы расширения OrderBy:
  • Вместо оператора orderby можно использовать методы расширения OrderBy:
Метод OrderBy()сортирует по возрастанию. Для сортировки по убыванию используется метод :
  • Метод OrderBy()сортирует по возрастанию. Для сортировки по убыванию используется метод :
Множественные критерии сортировки В наборах сложных объектов иногда встает ситуация, когда надо отсортировать не по одному, а сразу по нескольким полям. Для этого в запросе LINQ все критерии указываются в порядке приоритета через запятую:

Множественные критерии сортировки

  • В наборах сложных объектов иногда встает ситуация, когда надо отсортировать не по одному, а сразу по нескольким полям. Для этого в запросе LINQ все критерии указываются в порядке приоритета через запятую:
Результат программы:

Результат программы:

С помощью методов расширения то же самое можно сделать через метод ThenBy()(для сортировки по возрастанию) и ThenByDescending() (для сортировки по убыванию): Результат будет аналогичен предыдущему.
  • С помощью методов расширения то же самое можно сделать через метод ThenBy()(для сортировки по возрастанию) и ThenByDescending() (для сортировки по убыванию):

Результат будет аналогичен предыдущему.

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

Объединение, пересечение и разность коллекций

  • Кроме методов выборки LINQ имеет несколько методов, который позволяют из двух последовательностей объектов сгенерировать множество (то есть некий набор уникальных элементов): разность, объединение и пересечение.
Разность последовательностей С помощью метода Except можно получить разность двух последовательностей :

Разность последовательностей

  • С помощью метода Except можно получить разность двух последовательностей :
В данном случае из массива soft убираются все элементы, которые есть в массиве hard. Результатом операции будут два элемента:
  • В данном случае из массива soft убираются все элементы, которые есть в массиве hard. Результатом операции будут два элемента:
Пересечение последовательностей Для получения пересечения последовательностей, то есть общих для обоих наборов элементов, применяется метод Intersect :

Пересечение последовательностей

  • Для получения пересечения последовательностей, то есть общих для обоих наборов элементов, применяется метод Intersect :
Так как оба набора имеют только один общий элемент, то соответственно только он и попадет в результирующую выборку:
  • Так как оба набора имеют только один общий элемент, то соответственно только он и попадет в результирующую выборку:
Объединение последовательностей Для объединения двух последовательностей используется метод Union. Его результатом является новый набор, в котором имеются элементы, как из первой, так и из второй последовательности. Повторяющиеся элементы добавляются в результат только один раз:

Объединение последовательностей

  • Для объединения двух последовательностей используется метод Union. Его результатом является новый набор, в котором имеются элементы, как из первой, так и из второй последовательности. Повторяющиеся элементы добавляются в результат только один раз:
Результатом операции будет следующий набор:

Результатом операции будет следующий набор:

Если же нам нужно простое объединение двух наборов, то мы можем использовать метод Concat : Те элементы, которые встречаются в обоих наборах, дублируются.
  • Если же нам нужно простое объединение двух наборов, то мы можем использовать метод Concat :

Те элементы, которые встречаются в обоих наборах, дублируются.

Удаление дубликатов Для удаления дублей в наборе используется метод Distinct : Последовательное применение методов Concat и Distinct будет подобно действию метода Union.

Удаление дубликатов

  • Для удаления дублей в наборе используется метод Distinct :

Последовательное применение методов Concat и Distinct будет подобно действию метода Union.