LINQ - Consultas LINQ (.NET Core)


 Hoje vamos recordar alguns conceitos básicos sobre consultas LINQ.

Vamos iniciar recordando que uma consulta LINQ é um objeto IEnumerable genérico a partir do qual você obtém resultados, e, a variável à qual o resultado é atribuido é conhecido como variável de intervalo.

Esta variável é uma coleção não povoada; é apenas um objeto de consulta que pode recuperar dados. O LINQ não acessa os dados de origem até você tentar usar o objeto de consulta para trabalhar com os resultados. Isso é conhecido como execução adiada ou deferred execution.

Para consultas básicas, usar o LINQ com C# é muito fácil e intuitivo, pois o C# fornece palavras-chave que são mapeadas diretamente para os recursos que foram adicionados por meio de métodos de extensão. O benefício é que você pode escrever consultas tipadas de maneira muito semelhante ao SQL, obtendo suporte ao IntelliSense o tempo todo.

Vejamos um exemplo de consulta LINQ criado no Visual Studio 2019 Community usando uma Aplicação do tipo Console (.NET Core):

Você tem uma agenda que contém uma lista de dias em que você está ocupado e você deseja saber se você está ocupado em um dia específico.

Vamos implementar uma consulta LINQ para realizar esta tarefa:

using System;
using System.Collections.Generic;
using System.Linq;
using static System.Console;

namespace Linq_Consulta1
{

    class Program
    {
        private static List<DateTime> GetDatas()
        {
            return new List<DateTime>
            {
            new DateTime(2019, 1, 1),
            new DateTime(2019, 2, 5),
            new DateTime(2019, 3, 3),
            new DateTime(2019, 1, 3),
            new DateTime(2019, 1, 2),
            new DateTime(2019, 5, 4),
            new DateTime(2019, 2, 2),
            new DateTime(2019, 7, 5),
            new DateTime(2019, 6, 30),
            new DateTime(2019, 10, 14),
            new DateTime(2019, 11, 22),
            new DateTime(2019, 12, 1),
            new DateTime(2019, 5, 22),
            new DateTime(2019, 6, 7),
            new DateTime(2019, 1, 4)
            };
        }

        static void Main(string[] args)
        {
            WriteLine("Consultando a Agenda");

            var agenda = GetDatas();

            var estouOcupdaoEm = new DateTime(2019, 7, 5);

            var ocupado = from data in agenda
                                where data == estouOcupdaoEm
                                select data;

            foreach (var resultado in ocupado)
            {
                WriteLine($"Infelizmente estarei ocupado em {resultado:dd/MM/yyyy}");
            }

            ReadLine();
        }
    }
}

Neste código nossa consulta LINQ filtrou os dados que retornaram um objeto IEnumerable<DateTime> como resultado.

Mas existe uma maneira mais simples de executar essa consulta. Vejamos o mesmo exemplo usando o método de extensão Where:

        static void Main(string[] args)
        {
            var agenda = GetDatas();

            var estouOcupdaoEm = new DateTime(2019, 7, 5);

            foreach (var resultado in agenda.Where(d => d == estouOcupdaoEm))
            {
                WriteLine($"Infelizmente estarei ocupado em {resultado:dd/MM/yyyy}");
            }
            ReadLine();
        }

 

Neste exemplo eliminamos a consulta LINQ adicionando o método de extensão Where, e, ficamos com um código menor e mais conciso. O desempenho é o mesmo.

Mas qual é mais legível ?

Para uma consulta pequena com a do exemplo, o método de extensão Where pode ser melhor mas para uma consulta mais complexa é melhor usar uma consulta LINQ.

Somente um pequeno subconjunto dos métodos de extensão de consulta são mapeados para palavras-chave da linguagem; portanto, você normalmente vai misturar consultas LINQ com métodos de extensão como mostra o exemplo a seguir:

       static void Main(string[] args)
        {
            var agenda = GetDatas();

            var estouOcupdaoEm = new DateTime(2019, 7, 5);

            var resultado = (from d in agenda
                                    
where d == estouOcupdaoEm
                                     select d).
Count();

            if (resultado > 0)
                WriteLine($"Infelizmente estarei ocupado em {estouOcupdaoEm:dd/MM/yyyy}");
            else
                WriteLine($"Estarei disponível em {estouOcupdaoEm:dd/MM/yyyy}");

            ReadLine();
        }

Agora o método de extensão Count elimina o laço foreach, mas adicionamos a instrução if/then/else para mostrar a disponibilidade.

Além disso adicionamos parênteses para fazer a chamada ao método Count após o select.

Dessa forma as palavras-chave LINQ podem tornar sua consulta mais concisa e simples.

A tabela abaixo traz um resumo das principais palavras-chave usadas nas consultas LINQ:

Cláusula Descrição
from Especifica a fonte de dados e uma variável de intervalo;
where Filtra elementos da fonte de dados baseada em uma ou mais condições definidas
select Faz projeções, permitindo especificar o tipo e o formato dos elementos do resultado da consulta.
join Combina duas fontes de dados baseado em comparações de igualdade entre dois elementos especificados.
in Usada na cláusula join.
on Usada na cláusula join.
equals Palavra-chave contextual, utilizada na cláusula join. Substitui o operador == na comparação.
group Agrupa os resultados de uma consulta de acordo com valores específicos de uma determinada chave.
by Usada na cláusula group.
into Fornece um identificador para servir de referência aos resultados de uma cláusula de junção (join), agrupamento (group) ou projeção (select).
orderby Classifica os resultados em ordem ascendente ou descendente.
ascending Usada na cláusula orderby para determinar a classificação em ordem ascendente, que é a padrão, caso seja omitida.
descending Usada na cláusula orderby para determinar a classificação em ordem descendente.

Pense nisso ao criar suas consultas LINQ.

Eu sei é apenas LINQ, mas eu gosto...

"Eu sou o Alfa e o Ômega, o princípio e o fim, diz o Senhor, que é, e que era, e que há de vir, o Todo-Poderoso."
Apocalipse 1:8

Referências:

José Carlos Macoratti