Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Os operadores de consulta padrão são as palavras-chave e os métodos que formam o padrão LINQ. A linguagem C# define palavras-chave de consulta LINQ que você usa para a expressão de consulta mais comum. O compilador converte expressões usando essas palavras-chave para as chamadas de método equivalentes. As duas formas são sinônimos. Outros métodos que fazem parte do System.Linq namespace não têm palavras-chave de consulta equivalentes. Nesses casos, você deve usar a sintaxe do método. Esta seção aborda todas as palavras-chave do operador de consulta. O runtime e outros pacotes NuGet adicionam mais métodos projetados para trabalhar com consultas LINQ a cada versão. Os métodos mais comuns, incluindo aqueles que têm equivalentes de palavra-chave de consulta, são abordados nesta seção. Para obter a lista completa de métodos de consulta compatíveis com o Runtime do .NET, consulte a documentação da System.Linq.Enumerable API. Além dos métodos abordados aqui, essa classe contém métodos para concatenar fontes de dados, computando um único valor de uma fonte de dados, como uma soma, uma média ou outro valor.
Importante
Esses exemplos usam uma fonte de dados System.Collections.Generic.IEnumerable<T>. Fontes de dados baseadas em System.Linq.IQueryProvider usam as fontes de dados System.Linq.IQueryable<T> e as árvores de expressão. As árvores de expressão possuem limitações na sintaxe C# permitida. Além disso, todas as fontes de dados IQueryProvider
, como EF Core, podem impor mais restrições. Verifique a documentação da fonte de dados.
A maioria desses métodos opera em sequências, em que uma sequência é um objeto cujo tipo implementa a IEnumerable<T> interface ou a IQueryable<T> interface. Os operadores de consulta padrão fornecem recursos de consulta, incluindo filtragem, projeção, agregação, classificação e muito mais. Os métodos que compõem cada conjunto são membros estáticos das classes Enumerable e Queryable, respectivamente. Eles são definidos como métodos de extensão do tipo em que operam.
A distinção entre IEnumerable<T> e IQueryable<T> sequências determina como a consulta é executada em runtime.
Para IEnumerable<T>
, o objeto enumerável retornado captura os argumentos que foram passados para o método. Quando esse objeto é enumerado, a lógica do operador de consulta é empregada e os resultados da consulta são retornados.
Para IQueryable<T>
, a consulta é traduzida para uma árvore de expressão. A árvore de expressão pode ser traduzida para uma consulta nativa quando a fonte de dados pode otimizar a consulta. Bibliotecas como o Entity Framework convertem consultas LINQ em consultas SQL nativas que são executadas no banco de dados.
O exemplo de código a seguir demonstra como os operadores de consulta padrão podem ser usados para obter informações sobre uma sequência.
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
Sempre que possível, as consultas nesta seção usam uma sequência de palavras ou números como a origem de entrada. Para consultas em que relações mais complicadas entre objetos são usadas, as seguintes fontes que modelam uma escola são usadas:
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; }
}
Cada Student
tem um nível de escolaridade, um departamento primário e uma série de pontuações. Um Teacher
também tem uma propriedade City
que identifica o campus onde o docente ministra aulas. A Department
tem um nome e uma referência a um Teacher
que atua como chefe do departamento.
Você pode encontrar o conjunto de dados no repositório de origem.
Tipos de operadores de consulta
Os operadores de consulta padrão diferem no tempo de execução, dependendo se retornam um valor singleton ou uma sequência de valores. Os métodos que retornam um valor singleton (como Average e Sum) são executados imediatamente. Métodos que retornam uma sequência adiam a execução da consulta e retornam um objeto enumerável. Você pode usar a sequência de saída de uma consulta como a sequência de entrada para outra consulta. As chamadas para métodos de consulta podem ser encadeadas em uma consulta, o que permite que as consultas se tornem arbitrariamente complexas.
Operadores de consulta
Em uma consulta LINQ, a primeira etapa é especificar a fonte de dados. Em uma consulta LINQ, a from
cláusula vem primeiro para introduzir a fonte de dados (students
) e a variável de intervalo (student
).
//queryAllStudents is an IEnumerable<Student>
var queryAllStudents = from student in students
select student;
A variável de intervalo é como a variável de iteração em um foreach
loop, exceto que nenhuma iteração real ocorre em uma expressão de consulta. Quando a consulta é executada, a variável de intervalo serve como uma referência a cada elemento sucessivo em students
. Como o compilador pode inferir o tipo de student
, você não precisa especificá-lo explicitamente. Você pode introduzir mais variáveis de intervalo em uma let
cláusula. Para obter mais informações, consulte Cláusula let.
Observação
Para fontes de dados não genéricas, como ArrayList, a variável de intervalo deve ser explicitamente tipada. Para obter mais informações, consulte Como consultar um ArrayList com LINQ (C#) e a cláusula from.
Depois de obter uma fonte de dados, você poderá executar qualquer número de operações nessa fonte de dados:
-
Filtrar dados usando a
where
palavra-chave. -
Solicite dados usando as
orderby
palavras-chave e, opcionalmentedescending
. -
Agrupar dados usando as
group
palavras-chave e, opcionalmenteinto
. -
Unir dados usando a
join
palavra-chave. -
Dados do projeto usando a
select
palavra-chave.
Tabela de sintaxe de expressão de consulta
A tabela a seguir lista os operadores de consulta padrão que têm cláusulas de expressão de consulta equivalentes.
Transformações de dados com LINQ
Language-Integrated Query (LINQ) não se trata apenas de recuperar dados. Também é uma ferramenta poderosa para transformar dados. Usando uma consulta LINQ, você pode usar uma sequência de origem como entrada e modificá-la de várias maneiras para criar uma nova sequência de saída. Você pode modificar a sequência em si sem modificar os próprios elementos classificando e agrupando. Mas talvez o recurso mais poderoso das consultas LINQ seja a capacidade de criar novos tipos. A cláusula select cria um elemento de saída de um elemento de entrada. Use-o para transformar um elemento de entrada em um elemento de saída:
- Mescle várias sequências de entrada em uma única sequência de saída que tenha um novo tipo.
- Crie sequências de saída cujos elementos consistem em apenas uma ou várias propriedades de cada elemento na sequência de origem.
- Crie sequências de saída cujos elementos consistem nos resultados das operações executadas nos dados de origem.
- Crie sequências de saída em um formato diferente. Por exemplo, você pode transformar dados de linhas SQL ou arquivos de texto em XML.
Essas transformações podem ser combinadas de várias maneiras na mesma consulta. Além disso, a sequência de saída de uma consulta pode ser usada como a sequência de entrada para uma nova consulta. O exemplo a seguir transforma objetos em uma estrutura de dados na memória em elementos 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);
O código produz a seguinte saída 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>
Para obter mais informações, consulte Criando árvores XML em C# (LINQ to XML).
Você pode usar os resultados de uma consulta como fonte de dados para uma consulta subsequente. Este exemplo mostra como ordenar os resultados de uma operação de junção. Esta consulta cria uma junção de grupos e classifica os grupos com base no elemento de categoria, que ainda está no escopo. Dentro do inicializador de tipo anônimo, uma subconsulta ordena todos os elementos correspondentes da sequência de produtos.
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
*/
A consulta equivalente usando a sintaxe do método é mostrada no código a seguir:
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}");
}
}
Embora você possa usar uma orderby
cláusula com uma ou mais das sequências de origem antes da junção, geralmente não a recomendamos. Alguns provedores LINQ podem não preservar essa ordenação após a junção. Para obter mais informações, consulte Cláusula join.
Consulte também
- Enumerable
- Queryable
- cláusula select
- Métodos de Extensão
- LINQ (Palavras-chave de consulta)
- Tipos anônimos