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:
Obtenha a(s) fonte(s) de dados.
Crie a consulta.
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
, Where
e 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 evensQuery
de 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.