Compartilhar via


Escrevendo sua primeira consulta LINQ (Visual Basic)

Uma consulta é uma expressão que recupera dados de uma fonte de dados. As consultas são expressas em uma linguagem de consulta dedicada. Ao longo do tempo, diferentes idiomas foram desenvolvidos para diferentes tipos de fontes de dados, por exemplo, SQL para bancos de dados relacionais e XQuery para XML. Isso torna necessário que o desenvolvedor de aplicativos aprenda uma nova linguagem de consulta para cada tipo de fonte de dados ou formato de dados com suporte.

O LINQ simplifica essa situação ao oferecer um modelo consistente para trabalhar com os dados em vários tipos de fontes e formatos de dados. Em uma consulta LINQ, você está sempre trabalhando com objetos. 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 e entidades, coleções do .NET Framework e qualquer outra fonte ou formato para o qual um provedor LINQ está disponível. Este documento descreve as três fases da criação e do uso de consultas LINQ básicas.

Três estágios de uma operação de consulta

As operações de consulta LINQ consistem em três ações:

  1. Obtenha a fonte de dados ou as fontes.

  2. Crie a consulta.

  3. Executar a consulta.

No LINQ, a execução de uma consulta é distinta da criação da consulta. Você não recupera dados apenas criando uma consulta. Este ponto é discutido mais detalhadamente mais adiante neste tópico.

O exemplo a seguir ilustra as três partes de uma operação de consulta. O exemplo usa uma matriz de inteiros como uma fonte de dados conveniente para fins de demonstração. No entanto, os mesmos conceitos também se aplicam a outras fontes de dados.

Observação

Na Página de Compilação, Designer de Projeto (Visual Basic), verifique se a Opção Inferir está Ativada.

' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}

' Query creation.
Dim evensQuery = From num In numbers
                 Where num Mod 2 = 0
                 Select num

' Query execution.
For Each number In evensQuery
    Console.Write(number & " ")
Next

Saída:

0 2 4 6

A fonte de dados

Como a fonte de dados no exemplo anterior é uma matriz, ela dá suporte implícito à interface genérica IEnumerable<T> . É esse fato que permite que você use uma matriz como fonte de dados para uma consulta LINQ. Tipos que dão suporte IEnumerable<T> ou a uma interface derivada, como o genérico IQueryable<T> , são chamados de tipos queriráveis.

Como um tipo implicitamente consultável, a matriz não requer nenhuma modificação ou tratamento especial para servir como uma fonte de dados LINQ. O mesmo vale para qualquer tipo de coleção que suporta IEnumerable<T>, incluindo os genéricos List<T>, Dictionary<TKey,TValue>, e outras classes na biblioteca de classes do .NET Framework.

Se os dados de origem ainda não forem implementados IEnumerable<T>, um provedor LINQ será necessário para implementar a funcionalidade dos operadores de consulta padrão para essa fonte de dados. Por exemplo, LINQ to XML manipula o trabalho de carregar um documento XML em um tipo queryable XElement , conforme mostrado no exemplo a seguir. Para obter mais informações sobre operadores de consulta padrão, consulte Visão geral dos operadores de consulta padrão (Visual Basic).

' Create a data source from an XML document.
Dim contacts = XElement.Load("c:\myContactList.xml")

Com o LINQ to SQL, primeiro você cria um mapeamento relacional de objeto em tempo de design, manualmente ou usando o LINQ to SQL Tools no Visual Studio no Visual Studio. Você grava suas consultas nos objetos e, em tempo de execução, LINQ to SQL manipula a comunicação com o banco de dados. No exemplo a seguir, customers representa uma tabela específica no banco de dados e Table<TEntity> dá suporte a genéricos IQueryable<T>.

' Create a data source from a SQL table.
Dim db As New DataContext("C:\Northwind\Northwnd.mdf")
Dim customers As Table(Of Customer) = db.GetTable(Of Customer)

Para obter mais informações sobre como criar tipos específicos de fontes de dados, consulte a documentação dos vários provedores LINQ. (Para obter uma lista desses provedores, consulte LINQ (Language-Integrated Query).) A regra básica é simples: uma fonte de dados LINQ é qualquer objeto que dê suporte à interface genérica IEnumerable<T> ou uma interface que herda dela.

Observação

Tipos como ArrayList, que também dão suporte à interface não genérica IEnumerable, podem ser usados como fontes de dados LINQ. Para obter um exemplo que usa um ArrayList, consulte Como consultar uma ArrayList com LINQ (Visual Basic).

A consulta

Na consulta, você especifica quais informações deseja recuperar da fonte de dados ou das fontes. Você também tem a opção de especificar como essas informações devem ser classificadas, agrupadas ou estruturadas antes de serem retornadas. Para habilitar a criação de consultas, o Visual Basic incorporou uma nova sintaxe de consulta ao idioma.

Quando ela é executada, a consulta no exemplo a seguir retorna todos os números pares de uma matriz de inteiros. numbers

' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}

' Query creation.
Dim evensQuery = From num In numbers
                 Where num Mod 2 = 0
                 Select num

' Query execution.
For Each number In evensQuery
    Console.Write(number & " ")
Next

A expressão de consulta contém três cláusulas: From, Wheree Select. A função específica e a finalidade de cada cláusula de expressão de consulta são discutidas em Operações básicas de consulta (Visual Basic). Para obter mais informações, consulte Consultas. Observe que, no LINQ, uma definição de consulta geralmente é armazenada em uma variável e executada posteriormente. A variável de consulta, como evensQuery no exemplo anterior, deve ser um tipo que pode ser consultado. O tipo de evensQuery é IEnumerable(Of Integer)atribuído pelo compilador usando inferência de tipo local.

É importante lembrar que a variável de consulta em si não toma nenhuma ação e não retorna dados. Ele armazena apenas a definição de consulta. No exemplo anterior, é o For Each loop que executa a consulta.

Execução da consulta

A execução da consulta é separada da criação da consulta. A criação da consulta define a consulta, mas a execução é disparada por um mecanismo diferente. Uma consulta pode ser executada assim que é definida (execução imediata) ou a definição pode ser armazenada e a consulta pode ser executada posteriormente (execução adiada).

Execução adiada

Uma consulta LINQ típica é semelhante à do exemplo anterior, na qual evensQuery é definida. Ele cria a consulta, mas não a executa imediatamente. Em vez disso, a definição de consulta é armazenada na variável de consulta evensQuery. Você executa a consulta mais tarde, normalmente usando um For Each loop, que retorna uma sequência de valores ou aplicando um operador de consulta padrão, como Count ou Max. Esse processo é chamado de execução adiada.

' Query execution that results in a sequence of values.
For Each number In evensQuery
    Console.Write(number & " ")
Next

' Query execution that results in a single value.
Dim evens = evensQuery.Count()

Para uma sequência de valores, você acessa os dados recuperados usando a variável de iteração no For Each loop (number no exemplo anterior). Como a variável de consulta contém evensQuerya definição de consulta em vez dos resultados da consulta, você pode executar uma consulta quantas vezes quiser usando a variável de consulta mais de uma vez. Por exemplo, você pode ter um banco de dados em seu aplicativo que está sendo atualizado continuamente por um aplicativo separado. Depois de criar uma consulta que recupera dados desse banco de dados, você pode usar um For Each loop para executar a consulta repetidamente, recuperando os dados mais recentes todas as vezes.

O exemplo a seguir demonstra como a execução adiada funciona. Depois evensQuery2 de definido e executado com um For Each loop, como nos exemplos anteriores, alguns elementos na fonte numbers de dados são alterados. Em seguida, um segundo For Each loop é executado evensQuery2 novamente. Os resultados são diferentes na segunda vez, porque o For Each loop executa a consulta novamente, usando os novos valores em numbers.

Dim numberArray() = {0, 1, 2, 3, 4, 5, 6}

Dim evensQuery2 = From num In numberArray
                  Where num Mod 2 = 0
                  Select num

Console.WriteLine("Evens in original array:")
For Each number In evensQuery2
    Console.Write("  " & number)
Next
Console.WriteLine()

' Change a few array elements.
numberArray(1) = 10
numberArray(4) = 22
numberArray(6) = 8

' Run the same query again.
Console.WriteLine(vbCrLf & "Evens in changed array:")
For Each number In evensQuery2
    Console.Write("  " & number)
Next
Console.WriteLine()

Saída:

Evens in original array:

0 2 4 6

Evens in changed array:

0 10 2 22 8

Execução imediata

Na execução adiada de consultas, a definição de consulta é armazenada em uma variável de consulta para execução posterior. Na execução imediata, a consulta é executada no momento de sua definição. A execução é disparada quando você aplica um método que requer acesso a elementos individuais do resultado da consulta. A execução imediata geralmente é forçada usando um dos operadores de consulta padrão que retornam valores únicos. Os exemplos são Count, Max, Averagee First. Esses operadores de consulta padrão executam a consulta imediatamente após serem aplicados, calculando e retornando um resultado único. Para obter mais informações sobre operadores de consulta padrão que retornam valores únicos, consulte Operações de Agregação, Operações de Elemento e Operações quantificadoras.

A consulta a seguir retorna uma contagem dos números pares em uma matriz de inteiros. A definição de consulta não é salva e numEvens é simples Integer.

Dim numEvens = (From num In numbers
                Where num Mod 2 = 0
                Select num).Count()

Você pode obter o mesmo resultado usando o Aggregate método.

Dim numEvensAgg = Aggregate num In numbers
                  Where num Mod 2 = 0
                  Select num
                  Into Count()

Você também pode forçar a execução de uma consulta chamando o método ToList ou ToArray em uma consulta (imediata) ou em uma variável de consulta (adiada), conforme mostrado no código a seguir.

' Immediate execution.
Dim evensList = (From num In numbers
                 Where num Mod 2 = 0
                 Select num).ToList()

' Deferred execution.
Dim evensQuery3 = From num In numbers
                  Where num Mod 2 = 0
                  Select num
' . . .
Dim evensArray = evensQuery3.ToArray()

Nos exemplos anteriores, evensQuery3 é uma variável de consulta, mas evensList é uma lista e evensArray é uma matriz.

Usar ToList ou ToArray forçar a execução imediata é especialmente útil em cenários em que você deseja executar a consulta imediatamente e armazenar em cache os resultados em um único objeto de coleção. Para obter mais informações sobre esses métodos, consulte Converter tipos de dados.

Você também pode fazer com que uma consulta seja executada usando um IEnumerable método como o IEnumerable.GetEnumerator método.

Consulte também