stringtranslate.com

Интегрированный запрос языка

Language Integrated Query ( LINQ , произносится как «линк») — компонент Microsoft .NET Framework , который добавляет собственные возможности запросов к данным в языки .NET , первоначально выпущенный как основная часть .NET Framework 3.5 в 2007 году.

LINQ расширяет язык добавлением выражений запросов , которые похожи на операторы SQL и могут использоваться для удобного извлечения и обработки данных из массивов , перечислимых классов , XML- документов, реляционных баз данных и сторонних источников данных. Другие применения, которые используют выражения запросов в качестве общей структуры для читаемого составления произвольных вычислений, включают построение обработчиков событий [1] или монадических парсеров . [2] Он также определяет набор имен методов (называемых стандартными операторами запросов или стандартными операторами последовательностей ), а также правила трансляции, используемые компилятором для трансляции выражений синтаксиса запросов в выражения с использованием стиля fluent (называемого синтаксисом методов Microsoft) с этими именами методов, лямбда-выражениями и анонимными типами .

Архитектура

API стандартного оператора запроса

В дальнейшем описания операторов основаны на применении работы с коллекциями. Многие операторы принимают другие функции в качестве аргументов. Эти функции могут быть предоставлены в форме именованного метода или анонимной функции.

Набор операторов запросов , определенных LINQ, предоставляется пользователю как API Standard Query Operator (SQO) . Операторы запросов, поддерживаемые API: [3]

Выбирать
Оператор Select выполняет проекцию на коллекцию для выбора интересных аспектов элементов. Пользователь предоставляет произвольную функцию в форме именованного или лямбда-выражения , которая проецирует элементы данных. Функция передается оператору как делегат . Это реализует функцию Map высшего порядка.
Где
Оператор Where позволяет определить набор правил предикатов, которые оцениваются для каждого объекта в коллекции, в то время как объекты, не соответствующие правилу, отфильтровываются. Предикат предоставляется оператору как делегат. Это реализует функцию Filter высшего порядка.
ВыбратьМногие
Для предоставленного пользователем сопоставления элементов коллекции с коллекциями семантически выполняются два шага. Во-первых, каждый элемент сопоставляется с соответствующей коллекцией. Во-вторых, результат первого шага сглаживается на один уровень. Select и Where оба реализуемы в терминах SelectMany, пока доступны singleton и пустые коллекции. Правила трансляции, упомянутые выше, по-прежнему обязывают поставщика LINQ предоставлять два других оператора. Это реализует функцию привязки высшего порядка.
Сумма / Мин / Макс / Среднее

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

Агрегат

Обобщенная сумма / минимум / максимум. Этот оператор принимает функцию, которая определяет, как два значения объединяются для формирования промежуточного или конечного результата. При желании можно указать начальное значение, что позволяет сделать тип результата агрегации произвольным. Кроме того, можно указать функцию завершения, которая преобразует результат агрегации в еще одно значение. Это реализует функцию высшего порядка Fold .

Присоединиться / ГруппаПрисоединиться
Оператор Join выполняет внутреннее соединение двух коллекций на основе сопоставления ключей для объектов в каждой коллекции. Он принимает две функции в качестве делегатов, по одной для каждой коллекции, которые он выполняет для каждого объекта в коллекции, чтобы извлечь ключ из объекта. Он также принимает еще один делегат, в котором пользователь указывает, какие элементы данных из двух сопоставленных элементов должны использоваться для создания результирующего объекта. Оператор GroupJoin выполняет групповое соединение . Как и оператор Select, результаты соединения являются экземплярами другого класса со всеми элементами данных обоих типов исходных объектов или их подмножеством.
Взять / ВзятьВ то время как
Оператор Take выбирает первые n объектов из коллекции, тогда как оператор TakeWhile, который принимает предикат, выбирает те объекты, которые соответствуют предикату (останавливаясь на первом объекте, который ему не соответствует).
Пропустить / ПропуститьПока
Операторы Skip и SkipWhile являются дополнениями к Take и TakeWhile — они пропускают первые n объектов из коллекции или те объекты, которые соответствуют предикату (в случае SkipWhile).
OfType
Оператор OfType используется для выбора элементов определенного типа.
Конкат
Оператор Concat объединяет две коллекции.
Сортировать по / Затем по
Оператор OrderBy используется для указания первичного порядка сортировки элементов в коллекции по некоторому ключу. По умолчанию порядок сортировки — по возрастанию, для изменения порядка на обратный используется оператор OrderByDescending . ThenBy и ThenByDescending указывают последующий порядок элементов. Функция для извлечения значения ключа из объекта указывается пользователем как делегат.
Обеспечить регресс
Оператор Reverse меняет порядок следования коллекции на противоположный.
ГруппироватьПо
Оператор GroupBy принимает функцию, которая извлекает ключевое значение и возвращает коллекцию IGrouping<Key, Values>объектов для каждого отдельного ключевого значения. IGroupingЗатем объекты можно использовать для перечисления всех объектов для конкретного ключевого значения.
Отчетливый
Оператор Distinct удаляет дублирующиеся экземпляры объекта из коллекции. Перегрузка оператора принимает объект сравнения равенства, который определяет критерии различия.
Объединение / Пересечение / Исключение
Эти операторы используются для выполнения операций объединения , пересечения и разности двух последовательностей соответственно. У каждого есть перегрузка, которая принимает объект сравнения равенства, который определяет критерии равенства элементов.
ПоследовательностьEqual
Оператор SequenceEqual определяет, равны ли все элементы в двух коллекциях и находятся ли они в одинаковом порядке.
Первый / ПервыйИлиПоУмолчанию / Последний / ПоследнийИлиПоУмолчанию
Эти операторы принимают предикат. Оператор First возвращает первый элемент, для которого предикат возвращает значение true, или, если ничего не соответствует, выдает исключение. Оператор FirstOrDefault похож на оператор First, за исключением того, что он возвращает значение по умолчанию для типа элемента (обычно пустую ссылку) в случае, если ничто не соответствует предикату. Оператор Last извлекает последний элемент, соответствующий предикату, или выдает исключение в случае, если ничто не соответствует. LastOrDefault возвращает значение элемента по умолчанию, если ничто не соответствует.
Одинокий
Оператор Single берет предикат и возвращает элемент, соответствующий предикату. Исключение возникает, если ни один или более одного элемента не соответствуют предикату.
SingleOrDefault
Оператор SingleOrDefault принимает предикат и возвращает элемент, соответствующий предикату. Если предикату соответствует более одного элемента, выдается исключение. Если предикату не соответствует ни один элемент, возвращается значение по умолчанию.
ElementAt
Оператор ElementAt извлекает элемент по заданному индексу в коллекции.
Любой / Все
Оператор Any проверяет, есть ли в коллекции элементы, соответствующие предикату. Он не выбирает элемент, но возвращает true, если хотя бы один элемент соответствует. Вызов any без предиката возвращает true, если коллекция непустая. Оператор All возвращает true, если все элементы соответствуют предикату.
Содержит
Оператор Contains проверяет, содержит ли коллекция заданный элемент.
Считать
Оператор Count подсчитывает количество элементов в данной коллекции. Перегрузка, принимающая предикат, подсчитывает количество элементов, соответствующих предикату.

Стандартный API оператора запроса также определяет определенные операторы, которые преобразуют коллекцию в другой тип: [3]

Расширения языка

Хотя LINQ в первую очередь реализован как библиотека для .NET Framework 3.5, он также определяет необязательные расширения языка, которые делают запросы первоклассной языковой конструкцией и предоставляют синтаксический сахар для написания запросов. Эти расширения языка изначально были реализованы в C# 3.0, [5] : 75  VB 9.0 , F# [6] и Oxygene , а другие языки, такие как Nemerle, объявили о предварительной поддержке. Расширения языка включают: [7]

Например, в запросе на выборку всех объектов в коллекции, количество которых SomePropertyменьше 10,

var results = from c in SomeCollection where c.SomeProperty < 10 select new { c.SomeProperty , c.OtherProperty } ;              foreach ( var result in results ) { Console.WriteLine ( result ) ; }     

типы переменных result , c и results выводятся компилятором в соответствии с сигнатурами методов, которые в конечном итоге используются. Основой для выбора методов является запрос expression-free translation result

var results = SomeCollection.Where ( c = > c.SomeProperty < 10 ) .Select ( c = > new { c.SomeProperty , c.OtherProperty } ) ;             результаты.ForEach ( x = > { Console.WriteLine ( x.ToString ( ) ) ; } )  

Поставщики LINQ

Спецификация C#3.0 определяет шаблон выражения запроса вместе с правилами перевода из выражения LINQ в выражение в подмножестве C# 3.0 без выражений LINQ. Перевод, определенный таким образом, фактически не типизирован, что, в дополнение к тому, что лямбда-выражения могут интерпретироваться как делегаты или деревья выражений, обеспечивает большую степень гибкости для библиотек, желающих представить части своего интерфейса как предложения выражений LINQ. Например, LINQ to Objects работает с IEnumerable<T>s и с делегатами, тогда как LINQ to SQL использует деревья выражений.

Деревья выражений лежат в основе механизма расширяемости LINQ, с помощью которого LINQ может быть адаптирован для многих источников данных. Деревья выражений передаются поставщикам LINQ, которые являются реализациями, специфичными для источника данных, которые адаптируют запросы LINQ для использования с источником данных. Если они выбирают это, поставщики LINQ анализируют деревья выражений, содержащиеся в запросе, чтобы сгенерировать основные части, необходимые для выполнения запроса. Это могут быть фрагменты SQL или любое другое совершенно иное представление кода в качестве дополнительных манипулируемых данных. LINQ поставляется с поставщиками LINQ для коллекций объектов в памяти, баз данных Microsoft SQL Server , наборов данных ADO.NET и XML-документов. Эти различные поставщики определяют различные разновидности LINQ:

LINQ для объектов

Поставщик LINQ to Objects используется для коллекций в памяти, используя локальный механизм выполнения запросов LINQ. Код, сгенерированный этим поставщиком, ссылается на реализацию стандартных операторов запросов, определенных в Sequenceшаблоне, и позволяет IEnumerable<T>запрашивать коллекции локально. Текущая реализация LINQ to Objects выполняет проверки реализации интерфейса, чтобы обеспечить быстрые тесты членства, подсчеты и операции индексированного поиска, когда они поддерживаются типом среды выполнения IEnumerable. [8] [9] [10]

LINQ to XML (ранее назывался XLINQ)

Поставщик LINQ to XML преобразует XML-документ в коллекцию XElementобъектов, которые затем запрашиваются с использованием локального механизма выполнения, который предоставляется как часть реализации стандартного оператора запроса. [11]

LINQ to SQL (ранее назывался DLINQ)

Поставщик LINQ to SQL позволяет использовать LINQ для запросов к базам данных Microsoft SQL Server , включая базы данных SQL Server Compact . Поскольку данные SQL Server могут находиться на удаленном сервере, и поскольку SQL Server имеет собственный механизм запросов, LINQ to SQL не использует механизм запросов LINQ. Вместо этого он преобразует запрос LINQ в запрос SQL , который затем отправляется на SQL Server для обработки. [12] Однако, поскольку SQL Server хранит данные как реляционные данные , а LINQ работает с данными, инкапсулированными в объекты, два представления должны быть сопоставлены друг с другом. По этой причине LINQ to SQL также определяет структуру сопоставления. Сопоставление выполняется путем определения классов, которые соответствуют таблицам в базе данных и содержат все или подмножество столбцов в таблице в качестве элементов данных. [13] Соответствие, наряду с другими атрибутами реляционной модели , такими как первичные ключи , указывается с помощью атрибутов, определенных LINQ to SQL . Например,

[Таблица(Имя="Клиенты")] public class Customer { [Столбец(IsPrimaryKey = true)] public int CustID ;       [Столбец] публичная строка CustName ; }   

Это определение класса сопоставляется с таблицей с именем Customers, а два члена данных соответствуют двум столбцам. Классы должны быть определены до того, как можно будет использовать LINQ to SQL. Visual Studio 2008 включает конструктор сопоставлений, который можно использовать для создания сопоставления между схемами данных в объекте, а также в реляционном домене. Он может автоматически создавать соответствующие классы из схемы базы данных , а также разрешать ручное редактирование для создания другого представления, используя только подмножество таблиц или столбцов в таблице. [13]

Отображение реализуется с помощью , DataContextкоторый принимает строку подключения к серверу и может использоваться для генерации , Table<T>где T — тип, к которому будет сопоставлена ​​таблица базы данных. Table<T>Инкапсулирует данные в таблице и реализует IQueryable<T>интерфейс, так что создается дерево выражений, которое обрабатывает поставщик LINQ to SQL. Он преобразует запрос в T-SQL и извлекает набор результатов с сервера базы данных. Поскольку обработка происходит на сервере базы данных, локальные методы, которые не определены как часть лямбда-выражений, представляющих предикаты, не могут использоваться. Однако он может использовать хранимые процедуры на сервере. Любые изменения в наборе результатов отслеживаются и могут быть отправлены обратно на сервер базы данных. [13]

LINQ для наборов данных

Поскольку поставщик LINQ to SQL (выше) работает только с базами данных Microsoft SQL Server , для поддержки любой общей базы данных LINQ также включает LINQ to DataSets. Он использует ADO.NET для управления связью с базой данных. После того, как данные находятся в ADO.NET Datasets, LINQ to DataSets выполняет запросы к этим наборам данных. [14]

Производительность

Непрофессиональные пользователи могут столкнуться с тонкостями в функциях и синтаксисе LINQ to Objects . Наивные шаблоны реализации LINQ могут привести к катастрофическому снижению производительности. [15] [16]

Производительность LINQ to XML и LINQ to SQL по сравнению с ADO.NET зависит от варианта использования. [17] [18]

ПЛИНК

Версия 4 .NET Framework включает PLINQ , или Parallel LINQ , параллельный механизм выполнения для запросов LINQ. Он определяет ParallelQuery<T>класс. Любая реализация интерфейса IEnumerable<T>может воспользоваться преимуществами механизма PLINQ, вызвав AsParallel<T>(this IEnumerable<T>)метод расширения, определенный классом ParallelEnumerable в пространстве имен System.Linq .NET Framework. [19] Механизм PLINQ может выполнять части запроса одновременно в нескольких потоках, обеспечивая более быстрые результаты. [20]

Предшествующие языки

Многие концепции, представленные LINQ, были первоначально протестированы в исследовательском проекте Microsoft Cω , ранее известном под кодовыми названиями X# (X Sharp) и Xen . Он был переименован в Cω после того, как в него был интегрирован Polyphonic C# (еще один исследовательский язык, основанный на принципах исчисления соединений ).

Cω пытается сделать хранилища данных (такие как базы данных и XML- документы) доступными с той же легкостью и безопасностью типов , что и традиционные типы, такие как строки и массивы . Многие из этих идей были унаследованы из более раннего инкубационного проекта в рамках команды WebData XML под названием X# и Xen. Cω также включает новые конструкции для поддержки параллельного программирования ; эти функции были в значительной степени получены из более раннего проекта Polyphonic C#. [21]

Впервые появившись в 2004 году в качестве предварительной версии компилятора, функции Cω впоследствии были использованы корпорацией Microsoft при создании функций LINQ, выпущенных в 2007 году в .NET версии 3.5 [22]. Конструкции параллелизма также были выпущены в слегка измененном виде в виде библиотеки под названием Joins Concurrency Library для C# и других языков .NET корпорацией Microsoft Research . [23]

Порты

Существуют порты LINQ для PHP (PHPLinq), JavaScript (linq.js), TypeScript (linq.ts) и ActionScript (ActionLinq), хотя ни один из них не является строго эквивалентом LINQ в языках, вдохновленных .NET, C#, F# и VB.NET (где он является частью языка, а не внешней библиотекой, и где он часто решает более широкий круг задач). [ необходима ссылка ]

Смотрите также

Ссылки

  1. ^ "Rx framework". 10 июня 2011 г.
  2. ^ "Монадические парсеры-комбинаторы с использованием C#3" . Получено 21.11.2009 .
  3. ^ ab "Стандартные операторы запросов". Microsoft . Получено 2007-11-30 .
  4. ^ "Перечислимый класс". msdn . Microsoft . Получено 15 февраля 2014 г. .
  5. ^ ab Скит, Джон (23 марта 2019 г.). C# in Depth . Мэннинг. ISBN 978-1617294532.
  6. ^ "Выражения запросов (F#)". Microsoft Docs . Получено 2012-12-19 .
  7. ^ "LINQ Framework" . Получено 2007-11-30 .
  8. ^ "Enumerable.ElementAt" . Получено 2014-05-07 .
  9. ^ "Enumerable.Contains" . Получено 2014-05-07 .
  10. ^ "Enumerable.Count" . Получено 2014-05-07 .
  11. ^ ".NET Language-Integrated Query for XML Data". 30 апреля 2007 г. Получено 2007-11-30 .
  12. ^ "LINQ to SQL". Архивировано из оригинала 2013-01-25 . Получено 2007-11-30 .
  13. ^ abc "LINQ to SQL: .NET Language-Integrated Query for Relational Data". 30 апреля 2007 г. Получено 2007-11-30 .
  14. ^ "LINQ to DataSets". Архивировано из оригинала 2013-01-25 . Получено 2007-11-30 .
  15. ^ Видер, Гай (21.12.2007). "Тест производительности LINQ: мой первый проект Visual Studio 2008" . Получено 08.02.2009 .
  16. ^ Парсонс, Джаред (2008). "Увеличение производительности запросов LINQ". Microsoft Developer Network . Получено 2014-03-19 . Хотя верно, что LINQ мощный и очень эффективный, большие наборы данных все еще могут вызывать неожиданные проблемы с производительностью.
  17. ^ Альва, Хайме (2010-08-06). "Потенциальные проблемы производительности с повторной компиляцией скомпилированных запросов LINQ". Microsoft Developer Network . Получено 2014-03-19 . При многократном вызове запроса с Entity Framework рекомендуемый подход — использовать скомпилированные запросы LINQ. Компиляция запроса приводит к снижению производительности при первом использовании запроса, но последующие вызовы выполняются намного быстрее.
  18. ^ Kshitij, Pandey (25.05.2008). "Сравнение производительности LinQ с SQL, ADO, C#" . Получено 08.02.2009 .
  19. ^ "ParallelEnumerable Class" . Получено 2014-05-07 .
  20. ^ "Программирование в эпоху параллелизма: параллельное программирование с PFX" . Получено 16 октября 2007 г.
  21. ^ Эйхерт, Стив; Вули, Джеймс Б.; Маргери, Фабрис (2008). LINQ в действии . Мэннинг. стр. 56–57 (как указано в ссылке поиска Google Books — в книге нет номеров страниц). ISBN 9781638354628.
  22. ^ Концепции, лежащие в основе языка C# 3.0 | Статьи | TomasP.Net Архивировано 12.02.2007 на Wayback Machine
  23. ^ "Библиотека параллелизма соединений" . Получено 2007-06-08 .

Внешние ссылки