Introdução ao LINQ no Visual Basic

O LINQ (Language-Integrated Query) 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 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 ofereça suporte ao LINQ. Você pode fazer tudo isso com elementos comuns da linguagem Visual Basic. Como suas consultas são escritas na linguagem Visual Basic, os resultados da consulta são retornados como objetos fortemente tipados. Esses objetos suportam o IntelliSense, que permite que você escreva código mais rapidamente e detete erros em suas consultas em tempo de compilação em vez de em tempo de execução. As consultas LINQ podem ser usadas como fonte de consultas adicionais para refinar os resultados. Eles também podem ser vinculados a controles para que os usuários possam visualizar 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

Executando os exemplos

Para executar os exemplos na introdução e na seção Estrutura de uma 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

Fornecedores 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 pega essa consulta e a traduz 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. Finalmente, ele converte objetos em dados quando você envia atualizações para a fonte de dados.

Visual Basic inclui os seguintes provedores LINQ.

Provider Description
LINQ para objetos O provedor LINQ to Objects permite que você consulte coleções e matrizes na memória. Se um objeto suportar a IEnumerable interface ou IEnumerable<T> , o provedor LINQ to Objects permitirá que você o consulte.

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

Para obter mais informações sobre o provedor LINQ to Objects, consulte LINQ to Objects.
LINQ para SQL O provedor LINQ to SQL permite consultar e modificar dados em um banco de dados do SQL Server. Isso facilita o mapeamento do modelo de objeto de 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 (O/R Designer). Esse designer é usado para criar um modelo de objeto em um aplicativo que mapeia para objetos em um banco de dados. O O/R Designer também fornece funcionalidade para mapear procedimentos armazenados e funções para o DataContext objeto, que gerencia a 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 LINQ to SQL, consulte LINQ to SQL. Para obter mais informações sobre o Object Relational Designer, consulte LINQ to SQL Tools in Visual Studio.
LINQ para XML O provedor LINQ to XML permite consultar e modificar XML. Você pode modificar XML na memória ou pode carregar XML e salvar XML em um arquivo.

Além disso, o provedor LINQ to XML habilita literais XML e propriedades de eixo XML que permitem que você escreva XML diretamente em seu código do Visual Basic. Para obter mais informações, consulte XML.
LINQ para DataSet O provedor 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 de consulta, agregação e atualização dos dados em seu conjunto de dados.

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

Estrutura de uma consulta LINQ

Uma consulta LINQ, geralmente referida 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 classificar, filtrar, agrupar e juntar, ou cálculos para aplicar 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. Esta cláusula identifica os dados de origem para 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 denominadas variáveis de intervalo ou variáveis de iteração. A From cláusula é necessária para uma consulta, exceto para Aggregate consultas, onde a From cláusula é opcional. Depois que o escopo e a origem da consulta forem identificados nas From cláusulas or Aggregate , 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 apenas acrescentar cláusulas de consulta adicionais ao final da consulta. Você pode dividir 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 retornar apenas campos selecionados da fonte de dados. As consultas LINQ retornam coleções enumeráveis de objetos fortemente tipados. 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 fazer a correspondência entre os campos retornados pela consulta e os 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 contendo 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 contenha uma coleção de objetos do 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 ordem como um 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 ordem para o cliente. Ele também inclui uma OrderTotal propriedade que contém a soma dos totais de todos os pedidos para esse cliente. (Esta consulta é equivalente a uma JUNÇÃO EXTERNA ESQUERDA.)

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 os outros namespaces que suportam consultas LINQ incluem métodos que você pode chamar para criar e refinar consultas com base nas necessidades do seu aplicativo. 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.

Da cláusula

Uma From cláusula ou uma Aggregate cláusula é necessária para iniciar uma consulta. Uma From cláusula 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 de seleção

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 consistirão nas variáveis de iteração especificadas pela From cláusula ou Aggregate .

Cláusula de onde

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

Encomendar por cláusula

Opcional. Uma Order By cláusula especifica a ordem de classificação das 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 de adesão

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 agregadas 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 de adesão ao grupo

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 agregada

Uma Aggregate cláusula ou uma From cláusula é necessária para iniciar uma consulta. Uma Aggregate cláusula aplica uma ou mais funções agregadas 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 faz o exemplo a seguir.

' 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 de arrendamento

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 distinta

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 de pulo

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, desde que uma condição especificada seja true e, em seguida, retorna 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 desde o 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 de consulta LINQ adicionais

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 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 do SQL Server, como tabelas, exibições e procedimentos armazenados, que deseja acessar usando um arquivo LINQ to SQL. Um arquivo LINQ to SQL tem uma extensão .dbml.

Quando você tiver uma conexão válida com um banco de dados do SQL Server, poderá adicionar um modelo de item LINQ to SQL Classes ao seu projeto. Isso exibirá o Object Relational Designer (designer O/R). O O/R Designer permite que você arraste os itens que você deseja acessar em seu código do Gerenciador de Banco de Dados do Gerenciador de Servidores/ para a superfície do designer. O arquivo LINQ to SQL adiciona um DataContext objeto ao seu projeto. Este objeto inclui propriedades e coleções para as tabelas e exibições que você deseja acessar e métodos para os procedimentos armazenados que você deseja chamar. Depois de salvar as alterações no arquivo LINQ to SQL (.dbml), você pode acessar esses objetos em seu código fazendo referência ao DataContext objeto definido pelo O/R Designer. O DataContext objeto para seu projeto é nomeado com base no nome do seu 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

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

  • 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 permitir 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 Recursos do Visual Basic que suportam 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 é acionada 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 diferida).

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 fazer referência ao 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. Este processo é conhecido como execução diferida.

As consultas também podem ser executadas quando são definidas, o que é referido como execução imediata. Você pode acionar 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 agregada, como Count, Sum, Average, Min, ou Max. Para obter mais informações sobre funções agregadas, consulte Cláusula agregada.

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

Para obter mais informações sobre a execução de consultas, consulte Escrevendo sua primeira consulta LINQ.

XML em Visual Basic

Os recursos XML no Visual Basic incluem literais XML e propriedades de eixo XML, que permitem que você facilmente criar, acessar, consultar e modificar XML em seu código. Os 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 subelementos 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, consulte XML.

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

Como fazer 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 associações

Como: Classificar resultados da consulta

Como: Filtrar resultados da consulta

Como contar, somar ou 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 (O/R Designer)

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

Consulte também