Introdução a LINQ no Visual Basic

Language-Integrated Query (LINQ) adiciona recursos de consulta ao Visual Basic e fornece recursos simples e poderosos quando você trabalha com todos os tipos de dados. Em vez de enviar uma consulta para um banco de dados a ser processado ou trabalhar com sintaxe de consulta diferente para cada tipo de dados que você está pesquisando, o LINQ introduz consultas como parte da linguagem do Visual Basic. Ele usa uma sintaxe unificada, independentemente do tipo de dados.

O LINQ permite consultar dados de um banco de dados SQL Server, XML, matrizes e coleções na memória, conjuntos de dados ADO.NET ou qualquer outra fonte de dados remota ou local que dê suporte ao LINQ. Você pode fazer tudo isso com elementos comuns da linguagem do Visual Basic. Como suas consultas são escritas na linguagem Visual Basic, os resultados da consulta são retornados como objetos fortemente tipado. Esses objetos dão suporte ao IntelliSense, o que permite escrever código mais rapidamente e detectar erros em suas consultas no tempo de compilação, em vez de em tempo de execução. As consultas LINQ podem ser usadas como a origem de consultas adicionais para refinar resultados. Eles também podem ser associados a controles para que os usuários possam exibir e modificar facilmente os resultados da consulta.

Por exemplo, o exemplo de código a seguir mostra uma consulta LINQ que retorna uma lista de clientes de uma coleção e os agrupa com base em sua localização.

' Obtain a list of customers.
Dim customers As List(Of Customer) = GetCustomers()

' Return customers that are grouped based on country.
Dim countries = From cust In customers
                Order By cust.Country, cust.City
                Group By CountryName = cust.Country
                Into CustomersInCountry = Group, Count()
                Order By CountryName

' Output the results.
For Each country In countries
    Debug.WriteLine(country.CountryName & " count=" & country.Count)

    For Each customer In country.CustomersInCountry
        Debug.WriteLine("   " & customer.CompanyName & "  " & customer.City)
    Next
Next

' Output:
'   Canada count=2
'      Contoso, Ltd  Halifax
'      Fabrikam, Inc.  Vancouver
'   United States count=1
'      Margie's Travel  Redmond

Como executar os exemplos

Para executar os exemplos na introdução e na estrutura de uma seção de consulta LINQ, inclua o código a seguir, que retorna listas de clientes e pedidos.

' Return a list of customers.
Private Function GetCustomers() As List(Of Customer)
    Return New List(Of Customer) From
        {
            New Customer With {.CustomerID = 1, .CompanyName = "Contoso, Ltd", .City = "Halifax", .Country = "Canada"},
            New Customer With {.CustomerID = 2, .CompanyName = "Margie's Travel", .City = "Redmond", .Country = "United States"},
            New Customer With {.CustomerID = 3, .CompanyName = "Fabrikam, Inc.", .City = "Vancouver", .Country = "Canada"}
        }
End Function

' Return a list of orders.
Private Function GetOrders() As List(Of Order)
    Return New List(Of Order) From
        {
            New Order With {.CustomerID = 1, .Amount = "200.00"},
            New Order With {.CustomerID = 3, .Amount = "600.00"},
            New Order With {.CustomerID = 1, .Amount = "300.00"},
            New Order With {.CustomerID = 2, .Amount = "100.00"},
            New Order With {.CustomerID = 3, .Amount = "800.00"}
        }
End Function

' Customer Class.
Private Class Customer
    Public Property CustomerID As Integer
    Public Property CompanyName As String
    Public Property City As String
    Public Property Country As String
End Class

' Order Class.
Private Class Order
    Public Property CustomerID As Integer
    Public Property Amount As Decimal
End Class

Provedores LINQ

Um provedor LINQ mapeia suas consultas LINQ do Visual Basic para a fonte de dados que está sendo consultada. Quando você escreve uma consulta LINQ, o provedor usa essa consulta e a converte em comandos que a fonte de dados poderá executar. O provedor também converte dados da origem para os objetos que compõem o resultado da consulta. Por fim, ele converte objetos em dados quando você envia atualizações para a fonte de dados.

O Visual Basic inclui os seguintes provedores LINQ.

Provedor Descrição
Objetos LINQ to O provedor de LINQ to Objects permite consultar coleções e matrizes na memória. Se um objeto for compatível com a interface ou IEnumerable a IEnumerable<T> interface, o provedor de LINQ to Objects permitirá que você o consulte.

Você pode habilitar o provedor de LINQ to Objects importando o System.Linq namespace, que é importado por padrão para todos os projetos do Visual Basic.

Para obter mais informações sobre o provedor de LINQ to Objects, consulte LINQ to Objects.
LINQ to SQL O provedor de LINQ to SQL permite consultar e modificar dados em um banco de dados SQL Server. Isso facilita o mapeamento do modelo de objeto para um aplicativo para as tabelas e objetos em um banco de dados.

O Visual Basic facilita o trabalho com LINQ to SQL incluindo o Object Relational Designer (Designer O/R). Este designer é usado para criar um modelo de objeto em um aplicativo que mapeia para objetos em um banco de dados. O Designer de O/R também fornece funcionalidade para mapear procedimentos armazenados e funções para o objeto, que gerencia a DataContext comunicação com o banco de dados e armazena o estado para verificações de simultaneidade otimistas.

Para obter mais informações sobre o provedor de LINQ to SQL, consulte LINQ to SQL. Para obter mais informações sobre o Designer Relacional de Objetos, consulte Ferramentas do LINQ to SQL no Visual Studio.
LINQ to XML O provedor de LINQ to XML permite consultar e modificar XML. Você pode modificar o XML na memória ou carregar XML e salvar XML em um arquivo.

Além disso, o provedor de LINQ to XML habilita literais XML e propriedades do eixo XML que permitem que você escreva XML diretamente no código do Visual Basic. Para obter mais informações, confira XML.
LINQ to DataSet O provedor de LINQ to DataSet permite consultar e atualizar dados em um conjunto de dados ADO.NET. Você pode adicionar o poder do LINQ a aplicativos que usam conjuntos de dados para simplificar e estender seus recursos para consultar, agregar e atualizar os dados em seu conjunto de dados.

Para obter mais informações, consulte LINQ to DataSet.

Estrutura de uma consulta LINQ

Uma consulta LINQ, geralmente conhecida como uma expressão de consulta, consiste em uma combinação de cláusulas de consulta que identificam as fontes de dados e as variáveis de iteração para a consulta. Uma expressão de consulta também pode incluir instruções para classificação, filtragem, agrupamento e junção ou cálculos a serem aplicados aos dados de origem. A sintaxe da expressão de consulta é semelhante à sintaxe do SQL; portanto, você pode achar muito da sintaxe familiar.

Uma expressão de consulta começa com uma From cláusula. Essa cláusula identifica os dados de origem de uma consulta e as variáveis que são usadas para se referir a cada elemento dos dados de origem individualmente. Essas variáveis são variáveis de intervalo nomeadas ou variáveis de iteração. A From cláusula é necessária para uma consulta, exceto para Aggregate consultas, em que a From cláusula é opcional. Depois que o escopo e a origem da consulta forem identificados nas cláusulas ou From cláusulasAggregate, você poderá incluir qualquer combinação de cláusulas de consulta para refinar a consulta. Para obter detalhes sobre cláusulas de consulta, consulte operadores de consulta LINQ do Visual Basic mais adiante neste tópico. Por exemplo, a consulta a seguir identifica uma coleção de origem de dados do cliente como a customers variável e uma variável de iteração chamada cust.

Dim customers = GetCustomers()

Dim queryResults = From cust In customers

For Each result In queryResults
    Debug.WriteLine(result.CompanyName & "  " & result.Country)
Next

' Output:
'   Contoso, Ltd  Canada
'   Margie's Travel  United States
'   Fabrikam, Inc.  Canada

Este exemplo é uma consulta válida por si só; no entanto, a consulta se torna muito mais poderosa quando você adiciona mais cláusulas de consulta para refinar o resultado. Por exemplo, você pode adicionar uma Where cláusula para filtrar o resultado por um ou mais valores. As expressões de consulta são uma única linha de código; você pode simplesmente acrescentar cláusulas de consulta adicionais ao final da consulta. Você pode interromper uma consulta em várias linhas de texto para melhorar a legibilidade usando o caractere de continuação de linha (_) sublinhado. O exemplo de código a seguir mostra um exemplo de uma consulta que inclui uma Where cláusula.

Dim queryResults = From cust In customers
                   Where cust.Country = "Canada"

Outra cláusula de consulta poderosa é a Select cláusula, que permite que você retorne apenas campos selecionados da fonte de dados. As consultas LINQ retornam coleções enumeráveis de objetos fortemente tipado. Uma consulta pode retornar uma coleção de tipos anônimos ou tipos nomeados. Você pode usar a Select cláusula para retornar apenas um único campo da fonte de dados. Quando você faz isso, o tipo da coleção retornada é o tipo desse único campo. Você também pode usar a Select cláusula para retornar vários campos da fonte de dados. Quando você faz isso, o tipo da coleção retornada é um novo tipo anônimo. Você também pode corresponder os campos retornados pela consulta aos campos de um tipo nomeado especificado. O exemplo de código a seguir mostra uma expressão de consulta que retorna uma coleção de tipos anônimos que têm membros preenchidos com dados dos campos selecionados da fonte de dados.

Dim queryResults = From cust In customers
               Where cust.Country = "Canada"
               Select cust.CompanyName, cust.Country

As consultas LINQ também podem ser usadas para combinar várias fontes de dados e retornar um único resultado. Isso pode ser feito com uma ou mais From cláusulas ou usando as Join cláusulas ou Group Join consulta. O exemplo de código a seguir mostra uma expressão de consulta que combina dados de cliente e pedido e retorna uma coleção de tipos anônimos que contêm dados de cliente e pedido.

Dim customers = GetCustomers()
Dim orders = GetOrders()

Dim queryResults = From cust In customers, ord In orders
           Where cust.CustomerID = ord.CustomerID
           Select cust, ord

For Each result In queryResults
    Debug.WriteLine(result.ord.Amount & "  " & result.ord.CustomerID & "  " & result.cust.CompanyName)
Next

' Output:
'   200.00  1  Contoso, Ltd
'   300.00  1  Contoso, Ltd
'   100.00  2  Margie's Travel
'   600.00  3  Fabrikam, Inc.
'   800.00  3  Fabrikam, Inc.

Você pode usar a Group Join cláusula para criar um resultado de consulta hierárquica que contém uma coleção de objetos de cliente. Cada objeto de cliente tem uma propriedade que contém uma coleção de todos os pedidos para esse cliente. O exemplo de código a seguir mostra uma expressão de consulta que combina dados de cliente e pedido como resultado hierárquico e retorna uma coleção de tipos anônimos. A consulta retorna um tipo que inclui uma CustomerOrders propriedade que contém uma coleção de dados de pedido para o cliente. Ele também inclui uma OrderTotal propriedade que contém a soma dos totais de todos os pedidos para esse cliente. (Essa consulta é equivalente a LEFT OUTER JOIN.)

Dim customers = GetCustomers()
Dim orders = GetOrders()

Dim queryResults = From cust In customers
                   Group Join ord In orders On
                     cust.CustomerID Equals ord.CustomerID
                     Into CustomerOrders = Group,
                          OrderTotal = Sum(ord.Amount)
                   Select cust.CompanyName, cust.CustomerID,
                          CustomerOrders, OrderTotal

For Each result In queryResults
    Debug.WriteLine(result.OrderTotal & "  " & result.CustomerID & "  " & result.CompanyName)
    For Each ordResult In result.CustomerOrders
        Debug.WriteLine("   " & ordResult.Amount)
    Next
Next

' Output:
'   500.00  1  Contoso, Ltd
'      200.00
'      300.00
'   100.00  2  Margie's Travel
'      100.00
'   1400.00  3  Fabrikam, Inc.
'      600.00
'      800.00

Há vários operadores de consulta LINQ adicionais que você pode usar para criar expressões de consulta poderosas. A próxima seção deste tópico discute as várias cláusulas de consulta que você pode incluir em uma expressão de consulta. Para obter detalhes sobre cláusulas de consulta do Visual Basic, consulte Consultas.

Operadores de consulta LINQ do Visual Basic

As classes no System.Linq namespace e nos outros namespaces que dão suporte a consultas LINQ incluem métodos que você pode chamar para criar e refinar consultas com base nas necessidades do aplicativo. O Visual Basic inclui palavras-chave para as seguintes cláusulas de consulta comuns. Para obter detalhes sobre cláusulas de consulta do Visual Basic, consulte Consultas.

Cláusula From

Uma Fromcláusula ou uma cláusula Aggregate é necessária para iniciar uma consulta. Uma cláusula From especifica uma coleção de origem e uma variável de iteração para uma consulta. Por exemplo:

' Returns the company name for all customers for which
' the Country is equal to "Canada".
Dim names = From cust In customers
            Where cust.Country = "Canada"
            Select cust.CompanyName

cláusula Select

Opcional. Uma Select cláusula declara um conjunto de variáveis de iteração para uma consulta. Por exemplo:

' Returns the company name and ID value for each
' customer as a collection of a new anonymous type.
Dim customerList = From cust In customers
                   Select cust.CompanyName, cust.CustomerID

Se uma Select cláusula não for especificada, as variáveis de iteração para a consulta consistem nas variáveis de iteração especificadas pela From cláusula ou Aggregate pela cláusula.

Cláusula Where

Opcional. Uma Where cláusula especifica uma condição de filtragem para uma consulta. Por exemplo:

' Returns all product names for which the Category of
' the product is "Beverages".
Dim names = From product In products
            Where product.Category = "Beverages"
            Select product.Name

cláusula Order By

Opcional. Uma Order By cláusula especifica a ordem de classificação para colunas em uma consulta. Por exemplo:

' Returns a list of books sorted by price in 
' ascending order.
Dim titlesAscendingPrice = From b In books
                           Order By b.price

cláusula Join

Opcional. Uma Join cláusula combina duas coleções em uma única coleção. Por exemplo:

' Returns a combined collection of all of the 
' processes currently running and a descriptive
' name for the process taken from a list of 
' descriptive names.
Dim processes = From proc In Process.GetProcesses
                Join desc In processDescriptions
                  On proc.ProcessName Equals desc.ProcessName
                Select proc.ProcessName, proc.Id, desc.Description

cláusula Group By

Opcional. Uma Group By cláusula agrupa os elementos de um resultado de consulta. Ele pode ser usado para aplicar funções de agregação a cada grupo. Por exemplo:

' Returns a list of orders grouped by the order date
' and sorted in ascending order by the order date.
Dim orderList = From order In orders
                Order By order.OrderDate
                Group By OrderDate = order.OrderDate
                Into OrdersByDate = Group

cláusula Group Join

Opcional. Uma Group Join cláusula combina duas coleções em uma única coleção hierárquica. Por exemplo:

' Returns a combined collection of customers and
' customer orders.
Dim customerList = From cust In customers
                   Group Join ord In orders On
                     cust.CustomerID Equals ord.CustomerID
                   Into CustomerOrders = Group,
                        TotalOfOrders = Sum(ord.Amount)
                   Select cust.CompanyName, cust.CustomerID,
                          CustomerOrders, TotalOfOrders

cláusula Aggregate

Uma Aggregatecláusula ou uma cláusula From é necessária para iniciar uma consulta. Uma Aggregate cláusula aplica uma ou mais funções de agregação a uma coleção. Por exemplo, você pode usar a Aggregate cláusula para calcular uma soma para todos os elementos retornados por uma consulta, como o exemplo a seguir faz.

' Returns the sum of all order amounts.
Dim orderTotal = Aggregate order In orders
                 Into Sum(order.Amount)

Você também pode usar a Aggregate cláusula para modificar uma consulta. Por exemplo, você pode usar a Aggregate cláusula para executar um cálculo em uma coleção de consultas relacionada. Por exemplo:

' Returns the customer company name and largest 
' order amount for each customer.
Dim customerMax = From cust In customers
                  Aggregate order In cust.Orders
                  Into MaxOrder = Max(order.Amount)
                  Select cust.CompanyName, MaxOrder

cláusula Let

Opcional. Uma Let cláusula calcula um valor e o atribui a uma nova variável na consulta. Por exemplo:

' Returns a list of products with a calculation of
' a ten percent discount.
Dim discountedProducts = From prod In products
                         Let Discount = prod.UnitPrice * 0.1
                         Where Discount >= 50
                         Select prod.Name, prod.UnitPrice, Discount

cláusula Distinct

Opcional. Uma Distinct cláusula restringe os valores da variável de iteração atual para eliminar valores duplicados nos resultados da consulta. Por exemplo:

' Returns a list of cities with no duplicate entries.
Dim cities = From item In customers
             Select item.City
             Distinct

cláusula Skip

Opcional. Uma Skip cláusula ignora um número especificado de elementos em uma coleção e, em seguida, retorna os elementos restantes. Por exemplo:

' Returns a list of customers. The first 10 customers
' are ignored and the remaining customers are
' returned.
Dim customerList = From cust In customers
                   Skip 10

cláusula Skip While

Opcional. Uma Skip While cláusula ignora elementos em uma coleção, contanto que uma condição especificada seja true e retorne os elementos restantes. Por exemplo:

' Returns a list of customers. The query ignores all
' customers until the first customer for whom
' IsSubscriber returns false. That customer and all
' remaining customers are returned.
Dim customerList = From cust In customers
                   Skip While IsSubscriber(cust)

cláusula Take

Opcional. Uma Take cláusula retorna um número especificado de elementos contíguos do início de uma coleção. Por exemplo:

' Returns the first 10 customers.
Dim customerList = From cust In customers
                   Take 10

cláusula Take While

Opcional. Uma Take While cláusula inclui elementos em uma coleção, desde que uma condição especificada seja true e ignore os elementos restantes. Por exemplo:

' Returns a list of customers. The query returns
' customers until the first customer for whom 
' HasOrders returns false. That customer and all 
' remaining customers are ignored.
Dim customersWithOrders = From cust In customers
                          Order By cust.Orders.Count Descending
                          Take While HasOrders(cust)

Usar recursos adicionais de consulta LINQ

Você pode usar recursos de consulta LINQ adicionais chamando membros dos tipos enumeráveis e consultáveis fornecidos pelo LINQ. Você pode usar esses recursos adicionais chamando um operador de consulta específico no resultado de uma expressão de consulta. Por exemplo, o exemplo a seguir usa o Enumerable.Union método para combinar os resultados de duas consultas em um resultado de consulta. Ele usa o Enumerable.ToList método para retornar o resultado da consulta como uma lista genérica.

Public Function GetAllCustomers() As List(Of Customer)
    Dim customers1 = From cust In domesticCustomers
    Dim customers2 = From cust In internationalCustomers

    Dim customerList = customers1.Union(customers2)

    Return customerList.ToList()
End Function

Para obter detalhes sobre recursos adicionais do LINQ, consulte a visão geral dos operadores de consulta padrão.

Conectar-se a um banco de dados usando LINQ to SQL

No Visual Basic, você identifica os objetos de banco de dados SQL Server, como tabelas, exibições e procedimentos armazenados, que você deseja acessar usando um arquivo LINQ to SQL. Um arquivo LINQ to SQL tem uma extensão .dbml.

Quando você tem uma conexão válida com um banco de dados SQL Server, pode adicionar um modelo de item LINQ to SQL Classes ao seu projeto. Isso exibirá o Object Relational Designer (designer de O/R). O Designer de O/R permite arrastar os itens que você deseja acessar em seu código doGerenciador de Servidores/Gerenciador do Banco de Dados para a superfície do designer. O arquivo LINQ to SQL adiciona um DataContext objeto ao seu projeto. Esse objeto inclui propriedades e coleções para as tabelas e exibições às quais você deseja acessar e métodos para os procedimentos armazenados que você deseja chamar. Depois de salvar suas alterações no arquivo LINQ to SQL (.dbml), você poderá acessar esses objetos em seu código fazendo referência ao DataContext objeto definido pelo Designer O/R. O DataContext objeto para seu projeto é nomeado com base no nome do arquivo LINQ to SQL. Por exemplo, um arquivo LINQ to SQL chamado Northwind.dbml criará um DataContext objeto chamado NorthwindDataContext.

Para obter exemplos com instruções passo a passo, consulte Como consultar um banco de dados e como chamar um procedimento armazenado.

Recursos do Visual Basic que suportam LINQ

O Visual Basic inclui outros recursos notáveis que simplificam o uso do LINQ e reduzem a quantidade de código que você deve escrever para executar consultas LINQ. Elas incluem o seguinte:

  • Tipos anônimos, que permitem criar um novo tipo com base em um resultado de consulta.

  • Variáveis digitadas implicitamente, que permitem adiar a especificação de um tipo e permitem que o compilador infera o tipo com base no resultado da consulta.

  • Métodos de extensão, que permitem estender um tipo existente com seus próprios métodos sem modificar o próprio tipo.

Para obter detalhes, consulte os recursos do Visual Basic que dão suporte a LINQ.

Execução de consulta adiada e imediata

A execução da consulta é separada da criação de uma consulta. Depois que uma consulta é criada, sua execução é disparada por um mecanismo separado. 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).

Por padrão, quando você cria uma consulta, a consulta em si não é executada imediatamente. Em vez disso, a definição de consulta é armazenada na variável usada para referenciar o resultado da consulta. Quando a variável de resultado da consulta é acessada posteriormente no código, como em um For…Next loop, a consulta é executada. Esse processo é chamado de execução adiada.

As consultas também podem ser executadas quando são definidas, o que é chamado de execução imediata. Você pode disparar a execução imediata aplicando um método que requer acesso a elementos individuais do resultado da consulta. Isso pode ser o resultado da inclusão de uma função de agregação, comoCount, Sum, Average, Min ou Max. Para obter mais informações sobre funções de agregação, consulte Cláusula agregada.

Usar os ToList métodos ou ToArray também forçará a execução imediata. Isso pode ser útil quando você deseja executar a consulta imediatamente e armazenar em cache os resultados. Para obter mais informações sobre esses métodos, consulte Converter tipos de dados.

Para obter mais informações sobre a execução da consulta, consulte Como gravar sua primeira consulta LINQ.

XML no Visual Basic

Os recursos XML no Visual Basic incluem literais XML e propriedades do eixo XML, que permitem criar, acessar, consultar e modificar XML facilmente em seu código. Literais XML permitem que você escreva XML diretamente em seu código. O compilador do Visual Basic trata o XML como um objeto de dados de primeira classe.

O exemplo de código a seguir mostra como criar um elemento XML, acessar seus subconjuntos e atributos e consultar o conteúdo do elemento usando LINQ.

' Place Imports statements at the top of your program.
Imports <xmlns:ns="http://SomeNamespace">

Module Sample1

    Sub SampleTransform()

        ' Create test by using a global XML namespace prefix.

        Dim contact =
            <ns:contact>
                <ns:name>Patrick Hines</ns:name>
                <ns:phone ns:type="home">206-555-0144</ns:phone>
                <ns:phone ns:type="work">425-555-0145</ns:phone>
            </ns:contact>

        Dim phoneTypes =
          <phoneTypes>
              <%= From phone In contact.<ns:phone>
                  Select <type><%= phone.@ns:type %></type>
              %>
          </phoneTypes>

        Console.WriteLine(phoneTypes)
    End Sub

End Module

Para obter mais informações, confira XML.

Tópico Descrição
XML Descreve os recursos XML no Visual Basic que podem ser consultados e que permitem incluir XML como objetos de dados de primeira classe no código do Visual Basic.
Consultas Fornece informações de referência sobre as cláusulas de consulta disponíveis no Visual Basic.
LINQ (Consulta Integrada à Linguagem) Inclui informações gerais, diretrizes de programação e exemplos para LINQ.
LINQ to SQL Inclui informações gerais, diretrizes de programação e exemplos para LINQ to SQL.
Objetos LINQ to Inclui informações gerais, diretrizes de programação e exemplos para LINQ to Objects.
LINQ to ADO.NET (página do portal) Inclui links para informações gerais, diretrizes de programação e exemplos para LINQ to ADO.NET.
LINQ to XML Inclui informações gerais, diretrizes de programação e exemplos para LINQ to XML.

Como e tópicos passo a passo

Como consultar um banco de dados

Como chamar um procedimento armazenado

Como modificar dados em um banco de dados

Como combinar dados com junções

Como classificar resultados de consulta

Como filtrar resultados de consulta

Como contar, somar ou fazer média de dados

Como localizar o valor mínimo ou máximo em um resultado de consulta

Como atribuir procedimentos armazenados para executar atualizações, inserções e exclusões (Designer Relacional de Objetos)

Capítulo 17: LINQ na programação do Visual Basic 2008

Confira também