LINQ - Usando
Linq para consultas e cálculos com coleções
![]() |
O modelo de programação LINQ ou Language Integrated Query ou linguagem de consulta integrada é um recurso disponível integralmente a partir da versão 3.5 da plataforma .NET que permite realizar consultas de dados em coleções de objetos, banco de dados, arquivos XML, textos, etc. |
Dessa forma a LINQ fornece uma metodologia que a princípio simplifica e unifica a implementação de qualquer tipo de acesso a dados.
As três principais divisões da linguagem LINQ são:
A linguagem LINQ esta integrada ao Framework da plataforma .NET e esta totalmente disponível para que você a utilize de acordo com o cenário com o qual esta lidando, e você pode usá-la diretamente em seu código quer seja na linguagem C# , VB .NET, J#, F#, etc.
O movimento em direção ao LINQ teve início na versão 3.0 da plataforma .NET quando foram introduzidas as coleções genéricas , os tipos anônimos, as variáveis tipadas por expressão, a inicialização direta de objetos e coleções e as expressões lambdas e árvores de expressões; esse arsenal de recursos preparou o terreno para que a linguagem LINQ fosse construída com o objetivo de realizar consultas de forma rápida simples e intuitiva em informações que estão em coleções.
OBS: A LINQ teve sua primeira aparição em setembro de 2005 como um tecnical preview. Atualmente na versão 4.0 da plataforma .NET a LINQ também inclui LINQ to Entities, a qual é parte da ADO .NET Entity Framework e Parallel LINQ (PLINQ)
Assim o grande tchan do LINQ é que ela foi criada com o objetivo de simplificar consultas a informações na memória em coleções como listas e arrays, bem como informações armazenadas em base de dados , documentos XML , arquivos e outras fontes de dados. Ela realiza uma mapeamento objeto Relacional de forma que o acesso a dados é feito através do framework LINQ e as instruções SQL são geradas implicitamente.
Usando o LINQ você não vai precisar conhecer SQL , XML , XPath, ADO .NET para acessar/atualizar dados pois após referenciar as classes LINQ e efetuar o mapeamento basta usar os recursos do framework LINQ para realizar as tarefas comuns de manutenção conhecidas como CRUD (Create, Update, Delete).
A figura abaixo representa a arquitetura da linguagem LINQ:
![]() |
Compare abaixo dois trechos de código com acesso a dados, o primeiro usando ADO .NET e o segundo usando LINQ (LINQ to SQL)
1- ADO .NET
Dim c As
SqlConnection = New SqlConnection(stringConexao) c.Open() Dim cmd As SqlCommand = New SqlCommand("SELECT p.ProductID, p.ProductName FROM Products p WHERE p.ProductName = @p0") cmd.Parameters.AddWithValue("@p0", "Teste“) Dim dr As DataReader = c.Execute(cmd) While dr.Read() Dim ID As String = dr.GetString(0) Dim ProductName As String = dr.GetString End While |
2- LINQ To SQL
Dim db as new
DataContext1() Dim consulta =
from p in db.Products where (p.ProductName=="Teste") |
O código ficou mais enxuto mais elegante, e , além da economia de código o LINQ continua fortemente tipado e usa os recursos do IntelliSense da plataforma .NET sendo que após efetuar o mapeamento usando as consultas LINQ você terá acesso aos campos da tabela de dados que foram mapeados sem precisar conhecer a sua estrutura de dados, poderá usar o Intellisense e outros recursos da plataforma .NET.
A sintaxe LINQ
A LINQ é baseado em um conjunto de operadores de consulta, definidos como métodos de extensão, que trabalham com qualquer objeto que implemente a interface IEnumerable<T>.
A sintaxe básica da linguagem é:
var <variável> =
from <elemento da lista> in <lista de dados> where <clausula> select <elemento> |
Dim <variável> =
from <elemento da lista> in <lista de dados> where <clausula> select <elemento> |
C# | VB .NET |
Exemplo usando a sintaxe VB .NET :
Dim dados = From produtos In db.Products Where produtos.UnitPrice > 50 Order By produtos.ProductName Select produtos.ProductName, produtos.UnitPrice |
A
consulta LINQ To SQL inicia com a cláusula From e em seguida o operador de condição Where depois ordenação com Order By, e, no final o operador de seleção Select.Um dos motivos desta inversão de ordens é o uso recurso IntelliSense, pois quando você indica primeiro a origem dos dados ele pode mostrar as listas de membros de tipos nos objetos em sua coleção.
Outro motivo , segundo Anders Hejlsberg , seria que a ordem esta mais próxima da nossa lógica de pensamento.
Quando você digita uma instrução SQL iniciando com Select na verdade você já esta pensando na origem dos dados , condições , agrupamentos. etc. (você concorda?)
A cláusula From é a mais importante do LINQ pois é usada em todas as consultas.
Uma consulta deve sempre começar com From. (O Select pode estar implícito o From não.)
LINQ to Objects
Neste artigo eu vou tratar do LINQ to Objects na plataforma .NET versão 4.0 cujo objetivo é realizar consultas sobre coleções que implementam as interfaces IEnumerable ou IEnumerable<T>, ou seja, Arrays, Listas genéricas do tipo List<T>, dicionários de dados, textos, etc.
Para poder usar LINQ to Objects basta definir o namespace System.Linq no seu projeto conforme a linguagem que estiver usando.
Nos exemplos usados neste artigo vamos usar LINQ to Objects focando nas consultas e nos operadores usando a linguagem C#.
1- Usando LINQ to Objects com DataGridView
A LINQ to Objects nos dá a capacidade de escrever código declarativo para retornar dados de coleções que implementam as interfaces IEnumerable ou IEnumerable<T>.
Neste primeiro exemplo vou criar um projeto Windows Forms usando o Visual C# 2010 Express Edition para exibir dados em um controle DataGridView.
Vou criar uma classe Funcionarios definindo algumas propriedades que iremos retornar. A seguir vamos declarar um objeto BindingList<> do tipo Funcionarios de forma que quando o usuário preencher cada caixa de texto os valores serão atribuídos às propriedades da classe e os objetos serão incluídos na coleção BindingList<>.
Para concluir vamos usar uma consulta LINQ para obter o resultado exibindo no controle DataGridView.
Abra o Visual C# 2010 Express Edition e crie um novo projeto do tipo Windows Forms no menu FIle-> New Project e informe o nome LinqToObjects_DataGridView;
A seguir no formulário padrão form1.cs inclua os controles GroupBox, TextBox , Button e DataGridView conforme o leiaute da figura abaixo:
![]() |
No início do formulário Form1.cs temos a declaração do objeto BindingList<> do tipo Funcionarios:
// declara um objeto BindingList<> do tipo FuncionariosA classe BindingList<T> Fornece uma coleção genérica que suporte vinculação de dados.
A classe BindingList<T> pode ser usada como uma
classe base para criar um mecanismo de ligação de dados bidirecional. A classe
BindingList<T> fornece uma implementação concreta e genérica da interface
IBindingList interface.
Essa é uma alternativa para implementar a interface IBindingList, que
pode ser difícil devido a interação sutil entre IBindingList, IEditableObject
e o associado CurrencyManager.
No menu Project clique em Add Class para incluir uma nova classe ao projeto com o nome Funcionarios.cs.
Em seguida defina o seguinte código para a classe Funcionarios:
namespace LinqToObjects_DataGridView { class Funcionarios { //Propriedades Automatica public string Nome { get; set; } public string Email { get; set; } } } |
Os namespaces usados no formulário Form1.cs são:
using
System;using
System.ComponentModel;using
System.Linq;using
System.Windows.Forms;No evento Click do botão Inclui na Lista temos o código abaixo que atribui os valores informados na caixas de texto as propriedades da classe e inclui os objetos na lista:
private void btnIncluiNaLista_Click(object sender, EventArgs e) { // Inclui objetos funcionarios à lista funcionarios.Add(new Funcionarios { Nome = txtNome.Text, Email = txtEmail.Text }); } |
No evento Click do botão Exibe Dados temos o código a seguir que realiza um consulta LINQ na lista de funcionarios e os exibe em um controle DataGridView:
private void btnExibeDados_Click(object sender, EventArgs e) { //consulta com linq para obter os funcionários da lista var consulta = from funci in funcionarios select funci; //exibição do resultado no datagridview gdvFuncionarios.DataSource = consulta.ToList(); } |
Executando o projeto e teremos o seguinte resultado:
![]() |
2- Usando LINQ to Objects com uma Cesta de Compras
Neste exemplo vou mostrar como podemos realizar consultas e efetuar cálculos usando LINQ.
Vamos simular uma cesta de comparas onde o usuário irá selecionar um produto, preço e quantidade exibidos em controles ComboBox e poderá incluir a seleção em um controle ListBox montando uma cesta de compras onde teremos o cálculo do valor total da cesta.
No menu Project clique em Add Windows Form e aceite o nome padrão Form2.cs.
A seguir inclua os seguintes controles : GroupBox, Combobox, Button, ListBox e TextBox conforme o leiaute abaixo:
![]() |
Agora vamos criar duas classes: uma para a cesta de compras chamada CestaCompras e outra para os produtos chamada Produto.
No menu Project clique em Add Class para incluir uma nova classe ao projeto com o nome CestaCompras.cs e defina o seguinte código na classe:
namespace LinqToObjects_DataGridView{ class CestaCompra { public string Produto { get; set; } public double Preco { get; set; } public int Quantidade { get; set; } } } |
No menu Project clique em Add Class para incluir uma nova classe ao projeto com o nome CestaCompras.cs e defina o seguinte código na classe:
namespace LinqToObjects_DataGridView{ class Produto { public string ProdutoNome { get; set; } public double ProdutoPreco { get; set; } } }
|
Os namespaces usados no formulário são:
using
System;using
System.Collections.Generic;using
System.Linq;using
System.Windows.Forms;No evento Load do formulário Form2.cs temos o código que irá popular os controles Combobox do formulário com base na classe Produto:
private void Form2_Load(object sender, EventArgs e) { //Cria uma lista de produtos var dataSource = new List<Produto>(); dataSource.Add(new Produto() { ProdutoNome = "Mouse", ProdutoPreco = 12.65 }); dataSource.Add(new Produto() { ProdutoNome = "PadMouse", ProdutoPreco = 11.25 }); dataSource.Add(new Produto() { ProdutoNome = "Teclado", ProdutoPreco = 10.56 }); dataSource.Add(new Produto() { ProdutoNome = "Monitor", ProdutoPreco = 356.41 }); dataSource.Add(new Produto() { ProdutoNome = "HD Samsumg 320 GB", ProdutoPreco = 156.18 }); dataSource.Add(new Produto() { ProdutoNome = "Memoria 2 GB", ProdutoPreco = 89.15 }); //define o databinding o produto this.cboProduto.DisplayMember = "ProdutoNome"; this.cboProduto.ValueMember = "ProdutoNome"; this.cboProduto.DataSource = dataSource; // torna somente leitura this.cboProduto.DropDownStyle = ComboBoxStyle.DropDownList; //define o databinding para o preco this.cboPreco.DisplayMember = "ProdutoPreco"; this.cboPreco.ValueMember = "ProdutoPreco"; this.cboPreco.DataSource = dataSource; // torna somente leitura this.cboPreco.DropDownStyle = ComboBoxStyle.DropDownList; //seleciona o primeiro elemento da combo cboquantidade cboQuantidade.SelectedIndex = 0; } |
Para atribuir valores na ComboBox cboQuantidade usamos a propriedade Items e atribuímos valores de 1 a 10;
No início do formulário Form2.cs temos a declaração que irá definir uma lista de objetos do tipo CestaCompras :
// declara um objeto List<> do tipo CestaComprasNo evento Click do botão - Incluir na Cesta de Compras - temos o código que irá atribuir os valores selecionados ao objeto incluindo-os na lista e a seguir calculando o preço e o valor total para exibição no formulário:
private void btnIncluiNaCesta_Click(object sender, EventArgs e) { // Inclui objetos CestaCompra a lista string nomeProduto = cboProduto.SelectedValue.ToString(); double precoProduto = Convert.ToDouble(cboPreco.SelectedValue); int qtde = Convert.ToInt32(cboQuantidade.SelectedItem); cesta.Add(new CestaCompra { Produto = nomeProduto, Preco =precoProduto, Quantidade = qtde }); // usando linq para consultar as propriedades da classe CestaCompras var q = from item in cesta select string.Format("Produto: {0} Preco: {1} Qtde: {2}", item.Produto, item.Preco, item.Quantidade); //Populando o ListBox com todas as propriedades de CestaCompras lstbCesta.Items.Clear(); lstbCesta.Items.AddRange(q.ToArray()); lstbCesta.Items.Add(""); // usando linq para calcular o preco de cada produto var preco = from item in cesta select (item.Preco * item.Quantidade); // usando linq para calcular o preco total usando os métodos de extensão agregados double[] Precos = preco.ToArray(); double total = Precos.Aggregate((a, b) => a + b); txtTotal.Text = total.ToString(); } |
Destaques do código acima:
Estamos realizando um cálculo para cada item da cesta multiplicando o preço pela quantidade:
var preco = from item in cesta select (item.Preco * item.Quantidade);
A seguir usamos o método Aggregate para somar os valores:
double[] Precos = preco.ToArray();
double total = Precos.Aggregate((a, b) => a + b);
A sintaxe deste método é a seguinte: Aggregate<(Of TSource>)(IEnumerable<(Of TSource>), Func<(Of TSource, TSource, TSource>))
O método Aggregate torna mais simples realizar um cálculo sobre uma seqüência de valores. Este método funciona chamando a função func uma vez para cada elemento na fonte. Cada vez que a função é chamada, Aggregate passa o elemento da seqüência e um valor agregado (como o primeiro argumento para func).
O primeiro elemento da fonte é usado como valor inicial agregado. O resultado da func substitui o valor agregado anterior.
O método Aggregate retorna o resultado final da func.
Abaixo vemos o resultado obtido:
![]() |
E assim mostramos como usar a LINQ para consultas e cálculos em coleções.
Pegue
projeto completo aqui:
LinqToObjects_DataGridView.zip
"Porque tudo o que há no mundo, a concupiscência da carne, a concupiscência dos olhos e a soberba da vida, não vem do Pai, mas sim do mundo..." 1 João 2:16
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
LINQ - Usando os operadores SKIP, TAKE e LET - Macoratti ...