Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Стандартные операторы запросов — это ключевые слова и методы, которые формируют шаблон LINQ. Язык C# определяет ключевые слова запроса LINQ , которые используются для наиболее распространенного выражения запроса. Компилятор преобразует выражения с помощью этих ключевых слов в эквивалентные вызовы метода. Две формы являются синонимами. Другие методы, которые являются частью System.Linq пространства имен, не имеют эквивалентных ключевых слов запроса. В этих случаях необходимо использовать синтаксис метода. В этом разделе рассматриваются все ключевые слова оператора запроса. Среда выполнения и другие пакеты NuGet с каждым выпуском добавляют дополнительные методы, предназначенные для работы с запросами LINQ. Наиболее распространенные методы, включая те, которые имеют эквиваленты ключевых слов запроса, рассматриваются в этом разделе. Полный список методов запросов, поддерживаемых средой выполнения .NET, см. в System.Linq.Enumerable документации по API. Помимо методов, описанных здесь, этот класс содержит методы для объединения источников данных, вычисления одного значения из источника данных, например суммы, среднего или другого значения.
Это важно
В этих примерах используется System.Collections.Generic.IEnumerable<T> источник данных. Источники данных, основанные на System.Linq.IQueryProvider, используют System.Linq.IQueryable<T> источники данных и деревья выражений. Деревья выражений имеют ограничения на допустимый синтаксис C#. Кроме того, каждый IQueryProvider
источник данных, например EF Core , может наложить больше ограничений. Ознакомьтесь с документацией по источнику данных.
Большинство этих методов работают на последовательностях, где последовательность является объектом, тип которого реализует IEnumerable<T> интерфейс или IQueryable<T> интерфейс. Стандартные операторы запросов предоставляют возможности запроса, включая фильтрацию, проекцию, агрегирование, сортировку и многое другое. Методы, составляющие каждый набор, являются статическими элементами Enumerable и Queryable классами соответственно. Они определяются как методы расширения типа, на который они работают.
Различие между IEnumerable<T> и IQueryable<T> последовательностями определяет, как выполняется запрос во время выполнения.
Для IEnumerable<T>
возвращаемый перечисляемый объект сохраняет аргументы, переданные методу. При перечислении этого объекта используется логика оператора запроса и возвращаются результаты запроса.
Для IQueryable<T>
, этот запрос преобразуется в дерево выражений. Дерево выражений можно преобразовать в собственный запрос, когда источник данных может оптимизировать запрос. Библиотеки, такие как Entity Framework , преобразуют запросы LINQ в собственные SQL-запросы, которые выполняются в базе данных.
В следующем примере кода показано, как стандартные операторы запросов можно использовать для получения сведений о последовательности.
string sentence = "the quick brown fox jumps over the lazy dog";
// Split the string into individual words to create a collection.
string[] words = sentence.Split(' ');
// Using query expression syntax.
var query = from word in words
group word.ToUpper() by word.Length into gr
orderby gr.Key
select new { Length = gr.Key, Words = gr };
// Using method-based query syntax.
var query2 = words.
GroupBy(w => w.Length, w => w.ToUpper()).
Select(g => new { Length = g.Key, Words = g }).
OrderBy(o => o.Length);
foreach (var obj in query)
{
Console.WriteLine($"Words of length {obj.Length}:");
foreach (string word in obj.Words)
Console.WriteLine(word);
}
// This code example produces the following output:
//
// Words of length 3:
// THE
// FOX
// THE
// DOG
// Words of length 4:
// OVER
// LAZY
// Words of length 5:
// QUICK
// BROWN
// JUMPS
По возможности запросы в этом разделе используют последовательность слов или чисел в качестве источника входных данных. Для запросов, где используются более сложные связи между объектами, используются следующие источники, моделиирующие школу:
public enum GradeLevel
{
FirstYear = 1,
SecondYear,
ThirdYear,
FourthYear
};
public class Student
{
public required string FirstName { get; init; }
public required string LastName { get; init; }
public required int ID { get; init; }
public required GradeLevel Year { get; init; }
public required List<int> Scores { get; init; }
public required int DepartmentID { get; init; }
}
public class Teacher
{
public required string First { get; init; }
public required string Last { get; init; }
public required int ID { get; init; }
public required string City { get; init; }
}
public class Department
{
public required string Name { get; init; }
public int ID { get; init; }
public required int TeacherID { get; init; }
}
Каждый Student
имеет класс, первичный отдел и ряд оценок. Также у Teacher
есть свойство City
, определяющее кампус, где учитель ведёт занятия. У Department
него есть имя и ссылка на Teacher
того, кто выступает в качестве руководителя отдела.
Набор данных можно найти в исходном репозитории.
Типы операторов запросов
Стандартные операторы запросов различаются в зависимости от того, возвращают ли они однотонное значение или последовательность значений. Эти методы, возвращающие одноэлементное значение (например Average , и Sum) выполняются немедленно. Методы, возвращающие последовательность, откладывают выполнение запроса и возвращают перечислимый объект. Вы можете использовать выходную последовательность одного запроса в качестве входной последовательности для другого запроса. Вызовы методов запроса можно объединить в один запрос, что позволяет запросам становиться произвольным сложным.
Операторы запроса
В запросе LINQ сначала необходимо указать источник данных. Предложение from
LINQ будет первым в запросе, чтобы ввести источник данных (students
) и переменную диапазона (student
).
//queryAllStudents is an IEnumerable<Student>
var queryAllStudents = from student in students
select student;
Переменная диапазона похожа на переменную итерации в foreach
цикле, за исключением того, что фактические итерации не выполняются в выражении запроса. При выполнении запроса переменная диапазона служит ссылкой на каждый последовательный элемент в students
. Так как компилятор может выводить тип student
, его не нужно указывать явным образом. В предложении let
можно ввести дополнительные переменные диапазона. Дополнительные сведения см. в предложении 'let' .
Примечание.
Для не универсальных источников данных, таких как ArrayList, переменная диапазона должна быть явно типизированной. Дополнительные сведения см. в статье "Запрос массива" с помощью LINQ (C#) и предложения.
После получения источника данных можно выполнить любое количество операций с этим источником данных:
-
Фильтрация данных с помощью ключевого
where
слова. -
Упорядочьте данные, используя
orderby
и, при необходимости,descending
ключевые слова. -
Группируйте данные с использованием ключевых слов
group
и, при необходимости,into
. - Присоедините данные с помощью ключевого слова
join
. -
Данные проекта с помощью ключевого
select
слова.
Таблица синтаксиса выражения запроса
В следующей таблице перечислены стандартные операторы запросов, имеющие эквивалентные предложения выражения запроса.
Преобразования данных с помощью LINQ
Language-Integrated LINQ касается не только извлечения данных. Это также мощный инструмент для преобразования данных. С помощью запроса LINQ можно использовать исходную последовательность в качестве входных данных и изменять ее различными способами для создания новой выходной последовательности. Вы можете сортировать и группировать, чтобы изменить саму последовательность, не изменяя сами элементы. Но, возможно, самая мощная функция запросов LINQ — это возможность создавать новые типы. Предложение select создает выходной элемент из входного элемента. Он используется для преобразования входного элемента в выходной элемент:
- Слияние нескольких входных последовательностей в одну выходную последовательность с новым типом.
- Создайте выходные последовательности, элементы которых состоят только из одного или нескольких свойств каждого элемента в исходной последовательности.
- Создайте выходные последовательности, элементы которых состоят из результатов операций, выполняемых в исходных данных.
- Создайте выходные последовательности в другом формате. Например, можно преобразовать данные из строк SQL или текстовых файлов в XML.
Эти преобразования можно объединить различными способами в одном запросе. Кроме того, выходная последовательность одного запроса может использоваться в качестве входной последовательности для нового запроса. В следующем примере объекты в структуре данных в памяти преобразуются в XML-элементы.
// Create the query.
var studentsToXML = new XElement("Root",
from student in students
let scores = string.Join(",", student.Scores)
select new XElement("student",
new XElement("First", student.FirstName),
new XElement("Last", student.LastName),
new XElement("Scores", scores)
) // end "student"
); // end "Root"
// Execute the query.
Console.WriteLine(studentsToXML);
Код создает следующие выходные данные XML:
<Root>
<student>
<First>Svetlana</First>
<Last>Omelchenko</Last>
<Scores>97,90,73,54</Scores>
</student>
<student>
<First>Claire</First>
<Last>O'Donnell</Last>
<Scores>56,78,95,95</Scores>
</student>
...
<student>
<First>Max</First>
<Last>Lindgren</Last>
<Scores>86,88,96,63</Scores>
</student>
<student>
<First>Arina</First>
<Last>Ivanova</Last>
<Scores>93,63,70,80</Scores>
</student>
</Root>
Дополнительные сведения см. в статье "Создание деревьев XML в C# (LINQ to XML)".
Результаты одного запроса можно использовать в качестве источника данных для последующего запроса. В этом примере показано, как упорядочить результаты операции соединения. Этот запрос создает соединение группы, а затем сортирует группы на основе элемента категории, который всё ещё находится в контексте. Внутри инициализатора анонимного типа вложенный запрос отсортировывает все элементы, соответствующие условию, из последовательности продуктов.
var orderedQuery = from department in departments
join student in students on department.ID equals student.DepartmentID into studentGroup
orderby department.Name
select new
{
DepartmentName = department.Name,
Students = from student in studentGroup
orderby student.LastName
select student
};
foreach (var departmentList in orderedQuery)
{
Console.WriteLine(departmentList.DepartmentName);
foreach (var student in departmentList.Students)
{
Console.WriteLine($" {student.LastName,-10} {student.FirstName,-10}");
}
}
/* Output:
Chemistry
Balzan Josephine
Fakhouri Fadi
Popov Innocenty
Seleznyova Sofiya
Vella Carmen
Economics
Adams Terry
Adaobi Izuchukwu
Berggren Jeanette
Garcia Cesar
Ifeoma Nwanneka
Jamuike Ifeanacho
Larsson Naima
Svensson Noel
Ugomma Ifunanya
Engineering
Axelsson Erik
Berg Veronika
Engström Nancy
Hicks Cassie
Keever Bruce
Micallef Nicholas
Mortensen Sven
Nilsson Erna
Tucker Michael
Yermolayeva Anna
English
Andersson Sarah
Feng Hanying
Ivanova Arina
Jakobsson Jesper
Jensen Christiane
Johansson Mark
Kolpakova Nadezhda
Omelchenko Svetlana
Urquhart Donald
Mathematics
Frost Gaby
Garcia Hugo
Hedlund Anna
Kovaleva Katerina
Lindgren Max
Maslova Evgeniya
Olsson Ruth
Sammut Maria
Sazonova Anastasiya
Physics
Åkesson Sami
Edwards Amy E.
Falzon John
Garcia Debra
Hansson Sanna
Mattsson Martina
Richardson Don
Zabokritski Eugene
*/
Эквивалентный запрос с использованием синтаксиса метода показан в следующем коде:
var orderedQuery = departments
.GroupJoin(students, department => department.ID, student => student.DepartmentID,
(department, studentGroup) => new
{
DepartmentName = department.Name,
Students = studentGroup.OrderBy(student => student.LastName)
})
.OrderBy(department => department.DepartmentName);
foreach (var departmentList in orderedQuery)
{
Console.WriteLine(departmentList.DepartmentName);
foreach (var student in departmentList.Students)
{
Console.WriteLine($" {student.LastName,-10} {student.FirstName,-10}");
}
}
Хотя вы можете использовать условие orderby
с одной или несколькими исходными последовательностями перед присоединением, обычно мы не рекомендуем это. Некоторые поставщики LINQ могут не сохранять порядок после соединения. Для получения дополнительных сведений см. предложение соединения .
См. также
- Enumerable
- Queryable
- Предложение select
- Методы расширения
- Ключевые слова запроса (LINQ)
- Анонимные типы