Quick Dev: LINQ Overview

Olá pessoal!   

Neste artigo temos uma visão geral sobre o LINQ, passando pela sua definição, pelos tipos de dados que o suportam, pelos LINQ Providers e pelos estágios da execução de uma consulta LINQ. Por fim, listo também alguns exemplos de consultas com LINQ em diferentes fontes de dados.

Definição

O LINQ (Language Integrated Query) já não é mais novidade, estando disponível desde a versão 3.5 do .NET Framework. Ele veio com o objetivo de adicionar capacidade de pesquisa nativa às linguagens .NET. Com ele podemos pesquisar, filtrar e navegar facilmente sobre coleções de dados, documentos XML, Datasets e até mesmo dados em base de dados SQL Server. Um dos pontos mais interessantes do LINQ é o fato de possibilitar a realização de consultas em todas estas diferentes fontes dados utilizando-se de uma sintaxe padrão. Veja abaixo um exemplo de como seria a recuperação de todos os botões de um determinado formulário (aplicação Windows Forms) através do LINQ e a exibição dos seus nomes em ordem alfabética em um controle ListBox.

        'Esta é a consulta LINQ. Note que a fonte de dados é a coleção de controles do
        'formulário corrente (Me.Controls) e que estou filtrando a consulta para obter
        'apenas os controles do tipo Button. Também estou ordenando a consulta por ordem
        'crescente do nome do controle, através da clausula Order By. Por fim, faço a seleção
        'do que quero que seja atribuído à variável qry.
        Dim qry As IEnumerable(Of Control) = _
            From buttons As Control In Me.Controls _
            Where TypeOf (buttons) Is Button _
            Order By buttons.Text _
            Select buttons

        'Neste ponto estou chamando a função Count, que passa a estar disponível em
        'objetos que implementam a interface IEnumerable
        Me.lblStatus.Text = String.Format("{0} botões encontrados", qry.Count)

        'Agora basta iterar sobre o resultado da consulta e exibir no ListBox
        Me.ltbLista.Items.Clear()
        For Each btn As Button In qry
            Me.ltbLista.Items.Add(btn.Text)
        Next

Fontes de Dados e Providers

Para que seja possível realizar consultas utilizando o LINQ, é necessário que o dado esteja em uma fonte de dados Linq-Enabled. Como exemplos de tais fontes de dados temos hoje coleções que implementem a interface IEnumerable e IEnumerable(T), blocos XML e documentos XML, Datasets do ADO .NET e bases de dados SQL Server . O acesso aos dados destas fontes de dados é realizado através de LINQ Providers, que são responsáveis por fazer a adaptação da consulta escrita em sintaxe LINQ para a implementação específica da fonte de dados. Como exemplo de LINQ Providers temos o LINQ to Objects, LINQ to XML, LINQ to Dataset, LINQ to Entities e o LINQ to SQL. Neste último, por exemplo, as consultas escritas em LINQ são transformadas em consultas SQL, afinal, a base de dados SQL Server só entende comandos SQL. Veja na imagem a seguir a ilustração desta estrutura descrita.   

Arquitetura LINQ
Arquitetura LINQ - Fonte: http://www.codeproject.com/KB/linq/UnderstandingLINQ.aspx

Estágios de uma consulta LINQ

O processo de acesso a uma fonte de dados com uma consulta LINQ e da obtenção do dado em si ocorre em três estágios. O primeiro é a definição da fonte de dados, que deve ser uma das citadas anteriormente. O segundo é a definição da consulta LINQ em si, onde é definido o dado que se quer obter. O terceiro, por fim, é a execução, a qual geralmente ocorre apenas quando começamos a iterar sobre a consulta através de um loop for each (último passo do exemplo anterior). A consulta é executada ainda em sua definição quando possui funções agregadas (p. ex. Sum, Count e Average) ou quando invocamos métodos como o ToArray e o ToList da variável de definição do range (a variável buttons no exemplo anterior).   

Exemplos

Para finalizar, gostaria de deixar claro a similaridade na estrutura da consulta LINQ nas diferentes fontes de dados. A seguir temos exemplos do LINQ sendo aplicado para filtrar uma coleção de objetos (LINQ to Objects) e para filtrar e obter dados de um documento XML (LINQ to XML). Vou deixar os exemplos do LINQ com ADO .NET (LINQ  to Entities, LINQ to Dataset e LINQ to SQL Server) para um próximo artigo, pois envolvem diversos conceitos que tornariam este artigo muito extenso. No entanto, tenha certeza: A estrutura LINQ é a mesma! O que varia é a forma como trabalhamos com cada um dos providers.  

Linq to Objects 

        'Assuma uma classe simples chamada Player, que contém duas propriedades name (string) e
        'scores (array de integer)
        Dim lsPlayers As New List(Of Player)

        'Vamos incluir alguns itens na nossa lista de joradores
        lsPlayers.Add(New Player With {.name = "Nelson", .scores = New Integer() {160, 167, 170}})
        lsPlayers.Add(New Player With {.name = "Jose", .scores = New Integer() {150, 157, 155}})
        lsPlayers.Add(New Player With {.name = "Alfredo", .scores = New Integer() {170, 167, 170}})
        lsPlayers.Add(New Player With {.name = "Coió", .scores = New Integer() {130, 137, 120}})

        'Vamos fazer uma consulta nesta lista, obtendo apenas os jogadores cuja
        'média de pontuação seja maior que 160, ordenando o resultado por nome e selecionando
        'todos os campos da entidade Player
        Dim qry As IEnumerable(Of Player) = _
            From plr As Player In lsPlayers _
            Where plr.scores.Average > 160 _
            Order By plr.name _
            Select plr

        'Por fim, vamos iterar sobre a consulta, incluindo o seu resultado em um listbox
        Me.ltbLista.Items.Clear()
        For Each plr As Player In qry
            Me.ltbLista.Items.Add(plr.name & vbTab & plr.scores.Average)
        Next

Linq to XML

        'Assuma um documento XML chamado NorthwindProducts.xml, onde o elemento raiz é
        'chamado NorthwindProducts e dentro dele há um array de um elemento do tipo Products
        Dim root As XElement = XElement.Load("NorthwindProducts.xml")

        'Carregado o documento, vamos listar todos os produtos, ordenando o resultado
        'pelo nome do produto
        Dim product As IEnumerable(Of XElement) = _
            From el In root.Descendants("Products") _
            Order By (el.Element("ProductName").Value) _
            Select el

        'Por fim, vamos preencher um listbox com o nome dos produtos encontrados pela
        'consulta
        Me.ltbListaLINQXML.Items.Clear()
        For Each el In product
            Me.ltbListaLINQXML.Items.Add(el.Element("ProductName").Value)
        Next

Referências

MCTS Self-Paced Training Kit (Exam 70-505): Microsoft .NET Framework 3.5 – Windows Forms Application Development
LINQ  no .NET Framework Developer Center: http://msdn.microsoft.com/en-us/netframework/aa904594.aspx
LINQ no Wikipedia: http://en.wikipedia.org/wiki/Language_Integrated_Query
Understanding LINQ: http://www.codeproject.com/KB/linq/UnderstandingLINQ.aspx

Posts Similares

  • Asp .Net MVC 3.0

    Olá pessoal! Neste post gostaria de deixar registrada uma recomendação para quem quer começar a estudar o ASP .NET MVC 3.0 e que de quebra também quer aprender algumas novidades do Visual Studio 2010. Trata-se de um tutorial criado por Scott Hanselman no site ASP .NET (www.asp.net): Getting Started with MVC3, que traz um passo-a-passo…

  • Quick Dev: Formulários não-retangulares

    Olá pessoal! Este é o primeiro post de uma nova sessão denominada “Quick Dev”. O objetivo desta sessão é explorar rapidamente algumas abordagens de desenvolvimento simples, porém, úteis.    Se você está se perguntando neste momento: porque estamos abordando questões de desenvolvimento em um blog de arquitetura? Eu recomendo ler o texto de John Davies (não errei…

  • Quick Dev: Melhorando a performance de aplicações ASP .NET

    Olá pessoal! Quem nunca se incomodou com o tempo levado para a recompilação de aplicações ASP .NET já publicadas? Pois é, cada vez que um arquivo “top-level” é alterado em sua aplicação ASP .NET, por padrão, toda a compilação do site feita no seu primeiro acesso é invalidada, causando uma recompilação no próximo acesso. São…

  • AppFabric Caching Services

    Olá pessoal, Em fevereiro de 2011 foi publicado mais um artigo que escrevi para a revista .net Magazine, em sua edição de número oitenta e dois. Com o título “AppFabric Caching Services – Funcionalidades, instalação, configuração e utilização” o artigo complementa um outro artigo publicado anteriormente na edição sessenta e nove (veja o post aqui),…

  • Quick Dev: Behind LINQ to SQL

    Você que já utiliza o LINQ to SQL já deve ter tido a curiosidade de saber como as suas consultas LINQ são transformadas em comandos SQL e principalmente, qual a estrutura destes comandos SQL. Como o LINQ to SQL gera um comando SQL para atualizar apenas um registro em uma tabela? Ele utiliza sua chave primária na clausula WHERE? Acredito que estas sejam questões muito importantes para nos embasarmos quando tivermos que decidir pela sua utilização ou estabelecermos os cenários em que podemos aplicá-lo. No artigo anterior dei um overview sobre o LINQ. Neste artigo conceituo o provider LINQ to SQL e demonstro como suas consultas LINQ são transformadas em comandos SQL.

  • Quick Dev: Connection Pooling

    Olá pessoal!  Continuando a série Quick Dev, neste artigo vou falar um pouco sobre pooling de conexões em uma aplicação .NET.  Para começar, a seguir temos uma definição simples de pool de conexões: trata-se de um cache de conexões de banco de dados, mantidas de forma que possam ser reutilizadas quando futuras requisições são necessárias. Em uma aplicação .NET…

Deixe um comentário