Introdução a consultas LINQ (C#)Introduction to LINQ Queries (C#)

Uma consulta é uma expressão que recupera dados de uma fonte de dados.A query is an expression that retrieves data from a data source. As consultas normalmente são expressas em uma linguagem de consulta especializada.Queries are usually expressed in a specialized query language. Diferentes linguagens foram desenvolvidas ao longo do tempo para os diversos tipos de fontes de dados, por exemplo, SQL para bancos de dados relacionais e o XQuery para XML.Different languages have been developed over time for the various types of data sources, for example SQL for relational databases and XQuery for XML. Portanto, os desenvolvedores precisaram aprender uma nova linguagem de consulta para cada tipo de fonte de dados ou formato de dados que eles tinham que oferecer suporte.Therefore, developers have had to learn a new query language for each type of data source or data format that they must support. A LINQ simplifica essa situação oferecendo um modelo consistente para trabalhar com dados em vários tipos de fontes e formatos de dados.LINQ simplifies this situation by offering a consistent model for working with data across various kinds of data sources and formats. Em uma consulta LINQ, você está sempre trabalhando com objetos.In a LINQ query, you are always working with objects. Você usa os mesmos padrões básicos de codificação para consultar e transformar dados em documentos XML, bancos de dados SQL, ADO.NET Conjuntos de Dados, coleções .NET e qualquer outro formato para o qual um provedor LINQ esteja disponível.You use the same basic coding patterns to query and transform data in XML documents, SQL databases, ADO.NET Datasets, .NET collections, and any other format for which a LINQ provider is available.

Três Partes de uma Operação de ConsultaThree Parts of a Query Operation

Todas as operações de consulta LINQ consistem em três ações distintas:All LINQ query operations consist of three distinct actions:

  1. Obter a fonte de dados.Obtain the data source.

  2. Criar a consulta.Create the query.

  3. Executar a consulta.Execute the query.

O exemplo a seguir mostra como as três partes de uma operação de consulta são expressas em código-fonte.The following example shows how the three parts of a query operation are expressed in source code. O exemplo usa uma matriz de inteiros como uma fonte de dados para sua conveniência. No entanto, os mesmos conceitos também se aplicam a outras fontes de dados.The example uses an integer array as a data source for convenience; however, the same concepts apply to other data sources also. Faremos referência a este exemplo todo o restante deste tópico.This example is referred to throughout the rest of this topic.

class IntroToLINQ
{
    static void Main()
    {
        // The Three Parts of a LINQ Query:
        // 1. Data source.
        int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

        // 2. Query creation.
        // numQuery is an IEnumerable<int>
        var numQuery =
            from num in numbers
            where (num % 2) == 0
            select num;

        // 3. Query execution.
        foreach (int num in numQuery)
        {
            Console.Write("{0,1} ", num);
        }
    }
}

A ilustração a seguir mostra a operação de consulta completa.The following illustration shows the complete query operation. No LINQ, a execução da consulta é distinta da própria consulta.In LINQ, the execution of the query is distinct from the query itself. Em outras palavras, você não recuperou nenhum dado apenas criando uma variável de consulta.In other words, you have not retrieved any data just by creating a query variable.

Diagrama da operação completa de consulta LINQ.

A Fonte de DadosThe Data Source

No exemplo anterior, como a fonte de dados é uma matriz, ela dá suporte à interface genérica IEnumerable<T> de forma implícita.In the previous example, because the data source is an array, it implicitly supports the generic IEnumerable<T> interface. Este fato significa que ele pode ser consultado com LINQ.This fact means it can be queried with LINQ. Uma consulta é executada em uma instrução foreach, e foreach requer IEnumerable ou IEnumerable<T>.A query is executed in a foreach statement, and foreach requires IEnumerable or IEnumerable<T>. Tipos que dão suporte a IEnumerable<T> ou uma interface derivada, como a genérica IQueryable<T>, são chamados tipos passíveis de consulta.Types that support IEnumerable<T> or a derived interface such as the generic IQueryable<T> are called queryable types.

Um tipo quepode ser consultado não requer nenhuma modificação ou tratamento especial para servir como fonte de dados LINQ.A queryable type requires no modification or special treatment to serve as a LINQ data source. Se os dados de origem ainda não estão na memória como um tipo querificável, o provedor LINQ deve representá-los como tal.If the source data is not already in memory as a queryable type, the LINQ provider must represent it as such. Por exemplo, LINQ to XMLLINQ to XML carrega um documento XML em um tipo XElement passível de consulta:For example, LINQ to XMLLINQ to XML loads an XML document into a queryable XElement type:

// Create a data source from an XML document.
// using System.Xml.Linq;
XElement contacts = XElement.Load(@"c:\myContactList.xml");

Com LINQ to SQLLINQ to SQL, você primeiro cria um mapeamento objeto-relacional na hora do design manualmente ou usando o LINQ para SQL Tools no Visual Studio.With LINQ to SQLLINQ to SQL, you first create an object-relational mapping at design time either manually or by using the LINQ to SQL Tools in Visual Studio. Você escreve suas consultas aos objetos e o LINQ to SQLLINQ to SQL manipula a comunicação com o banco de dados em tempo de execução.You write your queries against the objects, and at run-time LINQ to SQLLINQ to SQL handles the communication with the database. No exemplo a seguir, Customers representa uma tabela específica no banco de dados, e o tipo do resultado da consulta, IQueryable<T>, deriva de IEnumerable<T>.In the following example, Customers represents a specific table in the database, and the type of the query result, IQueryable<T>, derives from IEnumerable<T>.

Northwnd db = new Northwnd(@"c:\northwnd.mdf");  
  
// Query for customers in London.  
IQueryable<Customer> custQuery =  
    from cust in db.Customers  
    where cust.City == "London"  
    select cust;  

Para obter mais informações sobre como criar tipos específicos de fontes de dados, consulte a documentação dos vários provedores de LINQ.For more information about how to create specific types of data sources, see the documentation for the various LINQ providers. No entanto, a regra básica é muito simples: uma fonte IEnumerable<T> de dados LINQ é qualquer objeto que suporte a interface genérica, ou uma interface que herda dela.However, the basic rule is very simple: a LINQ data source is any object that supports the generic IEnumerable<T> interface, or an interface that inherits from it.

Observação

Tipos como ArrayList esse suportam IEnumerable a interface não genérica também podem ser usados como fonte de dados LINQ.Types such as ArrayList that support the non-generic IEnumerable interface can also be used as a LINQ data source. Para obter mais informações, consulte Como consultar uma ArrayList com LINQ (C#).For more information, see How to query an ArrayList with LINQ (C#).

A ConsultaThe Query

A consulta especifica quais informações devem ser recuperadas da fonte (ou fontes) de dados.The query specifies what information to retrieve from the data source or sources. Opcionalmente, uma consulta também especifica como essas informações devem ser classificadas, agrupadas e moldadas antes de serem retornadas.Optionally, a query also specifies how that information should be sorted, grouped, and shaped before it is returned. Uma consulta é armazenada em uma variável de consulta e é inicializada com uma expressão de consulta.A query is stored in a query variable and initialized with a query expression. Para tornar mais fácil escrever consultas, o C# introduziu uma nova sintaxe de consulta.To make it easier to write queries, C# has introduced new query syntax.

A consulta no exemplo anterior retorna todos os números pares da matriz de inteiros.The query in the previous example returns all the even numbers from the integer array. A expressão de consulta contém três cláusulas: from, where e select.The query expression contains three clauses: from, where and select. (Se você estiver familiarizado com o SQL, você deve ter notado que a ordem das cláusulas é invertida da ordem no SQL.) A from cláusula especifica a fonte where de dados, a select cláusula aplica o filtro e a cláusula especifica o tipo dos elementos retornados.(If you are familiar with SQL, you will have noticed that the ordering of the clauses is reversed from the order in SQL.) The from clause specifies the data source, the where clause applies the filter, and the select clause specifies the type of the returned elements. Essas e outras cláusulas de consulta são discutidas detalhadamente na seção Linguagem Integrada consulta (LINQ).These and the other query clauses are discussed in detail in the Language Integrated Query (LINQ) section. Por enquanto, o ponto importante é que no LINQ, a variável consulta em si não toma nenhuma ação e não retorna nenhum dado.For now, the important point is that in LINQ, the query variable itself takes no action and returns no data. Ele apenas armazena as informações necessárias para produzir os resultados quando a consulta for executada em um momento posterior.It just stores the information that is required to produce the results when the query is executed at some later point. Para obter mais informações sobre como as consultas são construídas nos bastidores, consulte Visão geral de operadores de consulta padrão (C#).For more information about how queries are constructed behind the scenes, see Standard Query Operators Overview (C#).

Observação

As consultas também podem ser expressas usando a sintaxe de método.Queries can also be expressed by using method syntax. Para obter mais informações, consulte Sintaxe de consulta e sintaxe de método em LINQ.For more information, see Query Syntax and Method Syntax in LINQ.

Execução da consultaQuery Execution

Execução AdiadaDeferred Execution

Conforme mencionado anteriormente, a variável de consulta armazena somente os comandos da consulta.As stated previously, the query variable itself only stores the query commands. A execução real da consulta é adiada até que você itere sobre a variável de consulta em uma instrução foreach.The actual execution of the query is deferred until you iterate over the query variable in a foreach statement. Esse conceito é conhecido como execução adiada e é demonstrado no exemplo a seguir:This concept is referred to as deferred execution and is demonstrated in the following example:

//  Query execution.
foreach (int num in numQuery)
{
    Console.Write("{0,1} ", num);
}

A instrução foreach também é o local em que os resultados da consulta são recuperados.The foreach statement is also where the query results are retrieved. Por exemplo, na consulta anterior, a variável de iteração num armazena cada valor (um de cada vez) na sequência retornada.For example, in the previous query, the iteration variable num holds each value (one at a time) in the returned sequence.

Como a própria variável de consulta nunca armazena os resultados da consulta, você poderá executá-la quantas vezes desejar.Because the query variable itself never holds the query results, you can execute it as often as you like. Por exemplo, você pode ter um banco de dados que está sendo atualizado continuamente por um aplicativo separado.For example, you may have a database that is being updated continually by a separate application. Em seu aplicativo, você poderia criar uma consulta que recupera os dados mais recentes e poderia executá-la repetidamente em algum intervalo para recuperar resultados diferentes a cada vez.In your application, you could create one query that retrieves the latest data, and you could execute it repeatedly at some interval to retrieve different results every time.

Forçando Execução ImediataForcing Immediate Execution

As consultas que realizam funções de agregação em um intervalo de elementos de origem devem primeiro iterar sobre esses elementos.Queries that perform aggregation functions over a range of source elements must first iterate over those elements. Exemplos dessas consultas são Count, Max, Average e First.Examples of such queries are Count, Max, Average, and First. Essas consultas são executadas sem uma instrução foreach explícita porque a consulta em si deve usar foreach para retornar um resultado.These execute without an explicit foreach statement because the query itself must use foreach in order to return a result. Observe também que esses tipos de consultas retornam um valor único e não uma coleção IEnumerable.Note also that these types of queries return a single value, not an IEnumerable collection. A consulta a seguir retorna uma contagem de números pares na matriz de origem:The following query returns a count of the even numbers in the source array:

var evenNumQuery =
    from num in numbers
    where (num % 2) == 0
    select num;

int evenNumCount = evenNumQuery.Count();

Para forçar a execução imediata de qualquer consulta e armazenar seus resultados em cache, você pode chamar os métodos ToList ou ToArray.To force immediate execution of any query and cache its results, you can call the ToList or ToArray methods.

List<int> numQuery2 =
    (from num in numbers
     where (num % 2) == 0
     select num).ToList();

// or like this:
// numQuery3 is still an int[]

var numQuery3 =
    (from num in numbers
     where (num % 2) == 0
     select num).ToArray();

Você também pode forçar a execução colocando o loop foreach imediatamente após a expressão de consulta.You can also force execution by putting the foreach loop immediately after the query expression. No entanto, ao chamar ToList ou ToArray, você também armazena em cache todos os dados em um único objeto de coleção.However, by calling ToList or ToArray you also cache all the data in a single collection object.

Confira tambémSee also