Partilhar 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 linguagens foram desenvolvidas 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 do aplicativo aprenda uma nova linguagem de consulta para cada tipo de fonte de dados ou formato de dados suportado.

O LINQ (Language-Integrated Query) simplifica a situação, oferecendo um modelo consistente para trabalhar com 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, conjuntos de dados e entidades ADO.NET, coleções do .NET Framework e qualquer outra fonte ou formato para o qual um provedor LINQ esteja disponível. Este documento descreve as três fases da criação e 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(s) fonte(s) de dados.

  2. Crie a consulta.

  3. Execute a consulta.

No LINQ, a execução de uma consulta é distinta da criação da consulta. Você não recupera nenhum dado 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.

Nota

Na página Compilar, Project Designer (Visual Basic), verifique se Option infer está definido como On.

' 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

Resultado:

0 2 4 6

A fonte de dados

Como a fonte de dados no exemplo anterior é uma matriz, ela suporta implicitamente a interface genérica IEnumerable<T> . É esse fato que permite que você use uma matriz como fonte de dados para uma consulta LINQ. Os tipos que suportam IEnumerable<T> ou uma interface derivada, como o genérico, IQueryable<T> são chamados de tipos consultá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 é verdadeiro para qualquer tipo de coleção que ofereça suporte IEnumerable<T>a , incluindo o genérico List<T>, Dictionary<TKey,TValue>e outras classes na biblioteca de classes do .NET Framework.

Se os dados de origem ainda não implementarem IEnumerable<T>o , 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 lida com o trabalho de carregar um documento XML em um tipo consultável 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, você primeiro cria um mapeamento objeto-relacional em tempo de design, manualmente ou usando o LINQ to SQL Tools no Visual Studio no Visual Studio . Você escreve suas consultas nos objetos e, em tempo de execução, o LINQ to SQL lida com 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> oferece suporte a arquivos 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 para os vários provedores LINQ. (Para obter uma lista desses provedores, consulte LINQ (Consulta Integrada à Linguagem).) A regra básica é simples: uma fonte de dados LINQ é qualquer objeto que suporta a interface genérica IEnumerable<T> ou uma interface que herda dela.

Nota

Tipos como ArrayList esse que suportam a interface não genérica IEnumerable também 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(s) fonte(s) de dados. 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 na linguagem.

Quando é executada, a consulta no exemplo a seguir retorna todos os números pares de uma matriz inteira, 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 de consulta básicas (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 consultável. O tipo de é IEnumerable(Of Integer), atribuído pelo compilador usando inferência de evensQuery tipo local.

É importante lembrar que a variável de consulta em si não realiza 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 de Consultas

A execução da consulta é separada da criação da consulta. A criação de consultas define a consulta, mas a execução é acionada 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 diferida).

Execução diferida

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 evensQueryde consulta . Você executa a consulta posteriormente, 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. Este processo é conhecido como execução diferida.

' 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, evensQuery, mantém a 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 sempre.

O exemplo a seguir demonstra como a execução adiada funciona. Depois evensQuery2 é 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()

Resultado:

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 da sua definição. A execução é acionada 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. Exemplos são Count, Max, Average, e First. Esses operadores de consulta padrão executam a consulta assim que são aplicados para calcular e retornar um resultado singleton. 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 de quantificador.

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 ToList método ou ToArray em uma consulta (imediata) ou 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 nos quais 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 Convertendo 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