Что такое linq и для чего используется приведите несколько примеров применения linq
Что такое linq и для чего используется приведите несколько примеров применения 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:
Простейшее определение запроса LINQ выглядит следующим образом:
Далее с помощью оператора where проводится фильтрация объектов, и если объект соответствует критерию (в данном случае начальная буква должна быть «Б»), то этот объект передается дальше.
Оператор orderby упорядочивает по возрастанию, то есть сортирует выбранные объекты.
Оператор select передает выбранные значения в результирующую выборку, которая возвращается LINQ-выражением.
Преимуществом подобных запросов также является и то, что они интуитивно похожи на запросы языка SQL, хотя и имеют некоторые отличия.
Методы расширения LINQ
Запрос teams.Where(t=>t.ToUpper().StartsWith(«Б»)).OrderBy(t => t) будет аналогичен предыдущему. Он состоит из цепочки методов Where и OrderBy. В качестве аргумента эти методы принимают делегат или лямбда-выражение.
Не каждый метод расширения имеет аналог среди операторов LINQ, но в этом случае можно сочетать оба подхода. Например, используем стандартный синтаксис linq и метод расширения Count(), возвращающий количество элементов в выборке:
Список используемых методов расширения LINQ
Select : определяет проекцию выбранных значений
Where : определяет фильтр выборки
OrderBy : упорядочивает элементы по возрастанию
OrderByDescending : упорядочивает элементы по убыванию
ThenBy : задает дополнительные критерии для упорядочивания элементов возрастанию
ThenByDescending : задает дополнительные критерии для упорядочивания элементов по убыванию
Join : соединяет две коллекции по определенному признаку
GroupBy : группирует элементы по ключу
ToLookup : группирует элементы по ключу, при этом все элементы добавляются в словарь
GroupJoin : выполняет одновременно соединение коллекций и группировку элементов по ключу
Reverse : располагает элементы в обратном порядке
All : определяет, все ли элементы коллекции удовлятворяют определенному условию
Any : определяет, удовлетворяет хотя бы один элемент коллекции определенному условию
Contains : определяет, содержит ли коллекция определенный элемент
Distinct : удаляет дублирующиеся элементы из коллекции
Except : возвращает разность двух коллекцию, то есть те элементы, которые создаются только в одной коллекции
Union : объединяет две однородные коллекции
Intersect : возвращает пересечение двух коллекций, то есть те элементы, которые встречаются в обоих коллекциях
Count : подсчитывает количество элементов коллекции, которые удовлетворяют определенному условию
Sum : подсчитывает сумму числовых значений в коллекции
Average : подсчитывает cреднее значение числовых значений в коллекции
Min : находит минимальное значение
Max : находит максимальное значение
Take : выбирает определенное количество элементов
Skip : пропускает определенное количество элементов
TakeWhile : возвращает цепочку элементов последовательности, до тех пор, пока условие истинно
SkipWhile : пропускает элементы в последовательности, пока они удовлетворяют заданному условию, и затем возвращает оставшиеся элементы
Concat : объединяет две коллекции
Zip : объединяет две коллекции в соответствии с определенным условием
First : выбирает первый элемент коллекции
FirstOrDefault : выбирает первый элемент коллекции или возвращает значение по умолчанию
Single : выбирает единственный элемент коллекции, если коллекция содердит больше или меньше одного элемента, то генерируется исключение
SingleOrDefault : выбирает первый элемент коллекции или возвращает значение по умолчанию
ElementAt : выбирает элемент последовательности по определенному индексу
ElementAtOrDefault : выбирает элемент коллекции по определенному индексу или возвращает значение по умолчанию, если индекс вне допустимого диапазона
Last : выбирает последний элемент коллекции
LastOrDefault : выбирает последний элемент коллекции или возвращает значение по умолчанию
LINQ в C#
Примеры использования LINQ в C#
Выбор из массива строк с использованием LINQ
C LINQ этот код можно сделать короче и выразительнее:
Как можно видеть, синтаксис запроса в LINQ очень сильно похож на SQL, хотя и имеет некоторые различия. При этом, наиболее простой запрос в LINQ выглядит следующим образом:
Если переводить запрос LINQ на обычный язык, но на нашем примере получится следующее:
«все элементы s из набора strings »
«у которых длина более 5»
Сортировка массива с использованием LINQ
Ещё один показательный пример — использование LINQ для сортировки данных, например, массива чисел. В разделе «Алгоритмы» представлено несколько алгоритмов, реализующих сортировку массива чисел. Например, рассмотрим код, реализующий сортировку выбором:
Это самый простой метод сортировки, однако, используя LINQ мы можем отсортировать массив буквально в одну строку:
массив будет отсортирован в порядке возрастания.
Методы расширения LINQ
В качестве параметров, методы расширения принимаю обычно делегат или лямбда-выражение. Также, используя методы расширения мы можем расширить варианты использования LINQ, например, мы можем отфильтровать массив строк и вывести количество слов в выборке, используя вот такую последовательность методов расшения:
Наиболее часто используемые методы расширения LINQ представлены ниже:
Об этих методах расширения LINQ более подробно в следующих статьях.
Итого
Использование возможностей LINQ в C# позволяет сделать ваш код более выразительным (понятным) для чтения и, одновременно, более лаконичным. В своих проектах вы можете использовать LINQ в SQL-стиле (что встречается довольно редко) или же использовать методы расширения, которые во многом повторяют операции выполняемые при SQL-подобном использовании LINQ, но и, при этом, упрощают использование LINQ, например, позволяя вычислять значения элементарных математических операций — подсчитывать средние значения, определять количество элементов выборки и так далее.
Общие сведения о LINQ
LINQ (Language-Integrated Query) предоставляет возможности выполнения запросов на уровне языка и API функции высшего порядка в C# и Visual Basic для написания выразительного декларативного кода.
Синтаксис запросов на основе языка
Это синтаксис запросов на основе языка:
Это тот же пример, использующий API IEnumerable :
LINQ является выразительной методикой
Это традиционный императивный код:
Цель написания кода заключается не только в создании нового Dictionary и его добавления с помощью цикла, но также в преобразовании существующего списка в словарь! LINQ позволяет выполнить эту задачу, тогда как принудительный код — нет.
Это эквивалентное выражение LINQ:
Код, использующий LINQ, является весьма удобным, так как он создает равные условия как для достижения цели, как и для написания кода, сохраняя при этом логику. Еще одним преимуществом является краткость кода. Большие части базы кода можно сократить на треть, как показано выше. Неплохо, правда?
Поставщики LINQ упрощают доступ к данным
Использование значительной части существующего ПО связано с обработкой данных из определенного источника (баз данных, JSON, XML и т. д.). Часто для этого требуется изучать новый API по каждому источнику данных, что может оказаться раздражающим фактором. LINQ упрощает эту задачу путем абстрагирования общих элементов доступа к данным в синтаксис запросов, который имеет один и тот же вид независимо от выбираемого источника данных.
При этом будут найдены все элементы XML с указанным значением атрибута:
Написать код для просмотра XML-документа вручную будет намного сложнее.
Поставщики LINQ можно использовать для реализации целого ряда задач, не ограничиваясь только взаимодействием с XML. LINQ to SQL является довольно минималистичным инструментом объектно-реляционного сопоставления (ORM) для базы данных сервера MSSQL. Библиотека Json.NET предоставляет эффективные возможности просмотра документов JSON с помощью LINQ. Кроме того, если библиотека с необходимыми вам функциями отсутствует, можно написать собственный поставщик LINQ!
Причины использования синтаксиса запроса
Зачем использовать синтаксис запроса? Этот вопрос возникает довольно часто. В конце концов, следующий код:
гораздо более лаконичен, чем этот:
Может быть, синтаксис API просто является самым кратким способом формирования синтаксиса запроса?
Нет. Синтаксис запроса позволяет использовать предложение let, которое дает возможность ввести и привязать переменную в области выражения и применять ее в последующих частях выражения. Можно воспроизвести тот же код только с помощью синтаксиса API, но, скорее всего, этот код будет трудночитаемым.
Поэтому возникает вопрос о том, можно ли просто использовать синтаксис запросов?
Ответом будет Да, если.
Ответом будет Нет, если.
Важные части LINQ
Полный список примеров LINQ см. на странице 101 LINQ Samples (101 пример LINQ).
Далее приводятся примеры демонстрации некоторых важных частей LINQ. Она не является исчерпывающей, так как LINQ предоставляет больше возможностей, чем показано здесь.
Спрямление списка списков:
Объединение двух наборов (с пользовательским блоком сравнения):
Пересечение двух наборов:
Упорядочение
Равенство свойств экземпляра
И, наконец, расширенный пример: определение равенства значений свойств двух экземпляров одного типа (взят и изменен на основе этой записи на сайте StackOverflow):
PLINQ
Рассмотрим следующий пример.
Этот код будет секционировать facebookUsers по потокам системы, суммировать общие лайки в каждом параллельном потоке, суммировать результаты, вычисленные каждым потоком, и выводить результат в виде понятной строки.
Параллелизуемые задания, использующие ресурсы ЦП, которые можно легко выразить через LINQ (другими словами, чистые функции без побочных эффектов) являются отличным кандидатом для PLINQ. Для работы с заданиями, которые имеют побочный эффект, рекомендуется рассмотреть возможность использования библиотеки параллельных задач.
Синтаксис LINQ
Аббревиатура LINQ обозначает целый набор технологий, создающих и использующих возможности интеграции запросов непосредственно в язык C#. Традиционно запросы к данным выражаются в виде простых строк без проверки типов при компиляции или поддержки IntelliSense. Кроме того, разработчику приходится изучать различные языки запросов для каждого типа источников данных: баз данных SQL, XML-документов, различных веб-служб и т. д. Технологии LINQ превращают запросы в удобную языковую конструкцию, которая применяется аналогично классам, методам и событиям.
Описание выражения запроса
Выражение запроса можно использовать для получения и преобразования данных из любого источника данных, поддерживающего LINQ. Например, можно одним запросом получить данные из базы данных SQL и создать на их основе выходной XML-поток.
Выражение запроса очень легко понять, поскольку в нем используется много знакомых конструкций языка C#.
Все переменные в выражениях запросов строго типизированы, хотя во многих случаях вам не нужно указывать тип явным образом, поскольку компилятор определит его автоматически. Дополнительные сведения см. в статье Отношения между типами в операциях запросов LINQ (C#).
Во время компиляции выражения запроса преобразуются в вызовы метода стандартного оператора запроса. Для преобразования используются правила, заданные в спецификации C#. Любой запрос, который может быть выражен с помощью синтаксиса запросов, также может быть выражен с помощью синтаксиса методов. Однако в большинстве случаев синтаксис запроса будет понятнее и лаконичнее. Дополнительные сведения см. в статьях C# language specification (Спецификация языка C#) и Общие сведения о стандартных операторах запроса (C#).
Мы рекомендуем при написании запросов LINQ использовать синтаксис запросов везде, где это возможно, а синтаксис метода — только если это совершенно необходимо. Между этими формами синтаксиса нет никакой разницы в семантике или производительности. Выражения запросов обычно более удобочитаемыми, чем аналогичные выражения с использованием синтаксиса метода.
Некоторых операции запросов, например Count или Max, не имеют эквивалентных предложений выражения для запросов и должны выражаться как вызовы методов. Синтаксис запросов и синтаксис методов можно сочетать друг с другом различными способами. Дополнительные сведения см. в статье Синтаксис запросов и синтаксис методов в LINQ (C#).
Выражения запросов могут компилироваться в деревья выражений или в делегаты, в зависимости от типа, к которому применяется конкретный запрос. Запросы IEnumerable компилируются в делегаты. Запросы IQueryable и IQueryable компилируются в деревья выражений. Дополнительные сведения см. в статье Деревья выражений.
Следующие шаги
Чтобы получить дополнительные сведения о LINQ, сначала ознакомьтесь с некоторыми основным понятиями в статье Основы выражения запроса, а затем переходите к документации по интересующей вас технологии LINQ.
Платформа ADO.NET Entity Framework: LINQ to Entities
Чтобы глубже разобраться в базовой концепции LINQ изучите статью о LINQ в C#.
Чтобы быстрее приступить к работе с LINQ в C#, переходите к руководству Работа с LINQ.
Введение в запросы LINQ (C#)
Три составляющие операции запроса
Все операции запросов LINQ состоят из трех отдельных действий:
получение источника данных;
В следующем примере показано, как эти три части операции запроса выражаются в исходном коде. В этом примере для удобства используется массив целых чисел в качестве источника данных. Тем не менее те же принципы применимы к другим источникам данных. Остальные процедуры этого раздела содержат ссылки на этот пример.
На следующем рисунке показана полная операция запроса. Выполнение запроса в LINQ отличается от самого запроса. Иными словами, данные не извлекаются путем создания переменной запроса.
Источник данных
Запрашиваемый тип не требует внесения изменений или специальной обработки, чтобы служить источником данных LINQ. Если источник данных не находится в памяти в качестве запрашиваемого типа, поставщик LINQ должен представить его как таковой. Например, LINQ to XML загружает XML-документ в запрашиваемый тип XElement:
Дополнительные сведения о способах создания определенных типов источников данных см. в документации для различных поставщиков LINQ. Но общее правило очень простое: источником данных LINQ является любой объект, который поддерживает универсальный интерфейс IEnumerable или интерфейс, наследуемый от него.
Такие типы как ArrayList, которые поддерживают неуниверсальный интерфейс IEnumerable, также можно использовать в качестве источника данных LINQ. Дополнительные сведения см. в разделе Практическое руководство. Выполнение запроса к ArrayList с помощью LINQ (C#).
Запрос
Запрос указывает, какую информацию нужно извлечь из источника или источников данных. Дополнительно в запросе можно указать, как следует сортировать, группировать и формировать возвращаемую информацию. Запрос хранится в переменной запроса и инициализируется выражением запроса. Чтобы упростить написание запросов, в C# был представлен новый синтаксис запроса.
Запросы могут также выражаться с помощью синтаксиса методов. Дополнительные сведения см. в разделе Синтаксис запросов и синтаксис методов в LINQ.
Выполнение запроса
Отложенное выполнение
Оператор foreach также является частью кода, в которой извлекаются результаты запроса. Например, в предыдущем запросе переменная итерации num содержит каждое значение (по одному за раз) в возвращенной последовательности.
Поскольку сама переменная запроса никогда не содержит результаты запроса, вы можете выполнять ее так часто, как это необходимо. Например, может иметься база данных, постоянно обновляемая отдельным приложением. В приложении можно создать один запрос, получающий самые последние данные, и регулярно выполнять его с некоторым интервалом, каждый раз получая разные результаты.
Принудительное немедленное выполнение
Чтобы принудительно вызвать немедленное выполнение любого запроса и кэшировать его результаты, вы можете вызвать методы ToList или ToArray.
Принудительно вызвать выполнение также можно, поместив цикл foreach сразу после выражения запроса. При этом путем вызова ToList или ToArray можно также кэшировать все данные в одном объекте коллекции.