C# - LINQ : Usando a sintaxe Fluente


 Neste artigo vamos rever o conceito de sintaxe Fluente (Fluent Syntax) em consultas LINQ.

A LINQ permite que você consulte qualquer coleção que implemente IEnumerable<T>, seja uma matriz, lista ou DOM XML, bem como fontes de dados remotas, como tabelas em um banco de dados do SQL Server.

Neste artigo vamos recordar os conceitos da sintaxe fluente descrevendo como encadear operadores de consultas para formar consultas mais complexas mostrando porque os métodos de extensão são importantes nesse processo. Veremos também como formular expressões lambda para um operador de consulta e apresentar novos operadores.

Recursos Usados:

LINQ - Encadeando operadores de consulta

Abra o VS 2017 Community e crie um projeto do tipo Console Application com o nome CShp_LINQ_FluentSyntax.

Vamos começar com um código bem simples conforme mostrado a seguir:

using System.Collections.Generic;
using System.Linq;
using static System.Console;
namespace CShp_LINQ_FluentSyntax
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] nomes = { "Macoratti", "Dionísio", "Henrique", "Maria", "Janice" };
            IEnumerable<string> consulta = nomes
                           .Where(n => n.Contains("a"))
                           .OrderBy(n => n.Length)
                           .Select(n => n.ToUpper());
            foreach (string nome in consulta)
                    WriteLine(nome);
            ReadLine();
        }
    }
}

Para criar consultas mais complexas, podemos anexar operadores de consultas adicionais na expressão de consulta criando uma cadeia.

Neste exemplo estamos extraindo todas as strings que contém a letra 'a', classificando-as pelo tamanho e depois convertendo o resultado para caixa alta.

A variável n usada no exemplo possui um escopo privado para cada uma das expressões lambdas usadas.

Os operadores de consulta Where, OrderBy e Select que resolvem métodos de extensão na classe Enumerable:

Os dados fluem da esquerda para a direita através da cadeia de operadores, de modo que os dados são primeiro filtrados, depois ordenados então projetados.

A seguir temos a assinatura de cada um dos métodos de extensão usados no exemplo:

  1. public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate)
  2. public static IEnumerable<TSource> OrderBy<TSource,TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)
  3. public static IEnumerable<TResult> Select<TSource,TResult>(this IEnumerable<TSource> source, Func<TSource,TResult> selector)

Quando os operadores de consulta são encadeados como neste exemplo, a sequência de sida de um operador é a entrada de sequência de próximo operador.

Na figura abaixo abaixo temos um esquema do fluxo de operação dos operadores encadeados :

Se quisermos podermos construir uma consulta para obter o mesmo resultado usando a seguinte sintaxe :

 IEnumerable<string> filtrado = nomes .Where (n => n.Contains ("a"));
 IEnumerable<string> ordenado = filtrado.OrderBy (n => n.Length);
 IEnumerable<string> consultaFinal = ordenado .Select (n => n.ToUpper());
 

A consultaFinal possui uma composição idêntica a consulta original, usada no exemplo.

Além disso cada etapa intermediária também compreende uma consulta válida que podemos executar:

foreach (string nome in filtrado)
       Console.Write (nome + "|");       // Macoratti|Maria|Janice|

foreach (string nome in ordenado)
        Console.Write (nome + "|");       //Maria|Janice|Macoratti|

foreach (string nome in consultaFinal)
         Console.Write (nome + "|");       // MARIA|JANICE|MACORATTI|

E porque os métodos de extensão são tão importantes assim ?

Que tal usar a sintaxe convencional de método estático para chamar os operadores na consulta. Veja como ia ficar:

            IEnumerable<string> filtrado = Enumerable.Where(nomes,n => n.Contains("a"));
            IEnumerable<string> ordenado = Enumerable.OrderBy(filtrado, n => n.Length);
            IEnumerable<string> consultaFinal = Enumerable.Select(ordenado,n => n.ToUpper());

É assim que de fato como o compilador traduz as chamadas dos métodos de extensão.

Usando a sintaxe fluente temos o reflexo do fluxo de dados mostrado na sintaxe da consulta, da esquerda para direita conforme mostra o código a seguir:

  IEnumerable<string> consulta = nomes
                                 .Where(n => n.Contains("a"))
                                 .OrderBy(n => n.Length)
                                 .Select(n => n.ToUpper());

Isso facilita a legibilidade e compreensão da mesma.

"E estava ali um homem que, havia trinta e oito anos, se achava enfermo.Jesus disse-lhe: Levanta-te, toma o teu leito, e anda.Logo aquele homem ficou são; e tomou o seu leito, e andava. E aquele dia era sábado."
João 5:5-9

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Referências:


José Carlos Macoratti