.NET
: SQL vs LINQ
![]() |
Hoje vamos comparar consultas SQL com as respectivas consultas LINQ |
A escolha entre usar uma consulta SQL ou uma consulta LINQ depende do contexto em que você está trabalhando e das suas preferências pessoais. A seguir veremos alguns exemplos de consultas LINQ e SQL mostrando as diferenças.
SQL (Structured Query Language):
LINQ (Language Integrated Query):
Se você estiver trabalhando exclusivamente com bancos de dados relacionais e desejar otimização de desempenho, consultas SQL podem ser mais adequadas. No entanto se você estiver desenvolvendo em uma linguagem de programação que suporta LINQ e desejar aproveitar a verificação de tipo e a integração com a linguagem, LINQ pode ser uma boa escolha.
A seguir para ilustrar vamos comparar algumas consultas LINQ com a respectiva consulta SQL
Os exemplos da
LINQ mostrados a seguir pressupõem o uso do Entity Framework Core e um
DbContext chamado
db.
using (var db = new SeuDbContext()) { // ... as consultas LINQ são definidas aqui ... } |
Codigo de todos os
registros da tabela Produto.var resultado = db.Set<Produto>().Select(x => x.Codigo).ToList();SELECT Codigo FROM Produto
Codigo, Descricao e
Preco de todos os registros da tabela
Produto, criando um novo objeto anônimo para
cada resultado.
var resultado = db.Set<Produto>()
.Select(x => new
{
x.Codigo,
x.Descricao,
x.Preco
}).ToList();
SELECT Codigo, Descricao, Preco FROM Produto
Produto.var resultado = db.Set<Produto>().ToList();SELECT * FROM Produto
Codigo e Descricao, e
também calcula um novo valor chamado
CustoTotal (multiplicando Estoque
por Custo), atribuindo um alias a essa
nova coluna no resultado.var resultado = db.Set<Produto>() .Select(x => new { x.Codigo, x.Descricao, CustoTotal = x.Estoque * x.Custo }).ToList();SELECT Codigo, Descricao, Estoque * Custo as CustoTotal FROM Produto
Produto onde a propriedade
Codigo é igual a "1001".var resultado = db.Set<Produto>() .Where(x => x.Codigo == "1001") .ToList();SELECT * FROM Produto WHERE Codigo = '1001'
Produto onde a propriedade
Descricao contém a substring "MIE". Isso é
geralmente traduzido para um operador LIKE
no SQL.var resultado = db.Set<Produto>() .Where(x => x.Descricao.Contains("MIE")) .ToList();SELECT * FROM Produto WHERE Nome LIKE '%MIE%'
Produto onde a propriedade
Descricao começa com a string "ABC". Isso é
traduzido para um operador LIKE com um
curinga no final no SQL.var resultado = db.Set<Produto>() .Where(x => x.Descricao.StartsWith("ABC")) .ToList();SELECT * FROM Produto WHERE Codigo LIKE 'ABC%'
Produto onde a propriedade
Descricao termina com a string "ABC". Isso é
traduzido para um operador LIKE com um
curinga no início no SQL.
var resultado = db.Set<Produto>()
.Where(x => x.Descricao.EndsWith("ABC"))
.ToList();
SELECT * FROM Produto
WHERE Codigo LIKE '%ABC'
Produto onde a
propriedade Codigo está contida no
array de strings arr. Isso é traduzido
para um operador IN no SQL.var arr = new string[] {"A001", "B001", "C001" }; var resultado = db.Set<Produto>() .Where(x => arr.Contains(x.Codigo)) .ToList();SELECT * FROM Produto WHERE Codigo IN ('A001', 'B001', 'C001')
Produto onde a parte da data da
propriedade DataCriacao está dentro do
intervalo especificado (de 01/01/2022 a 31/12/2022).var inicio = new DateTime(2022, 1, 1); var fim = new DateTime(2022, 12, 31); var resultado = db.Set<Produto>() .Where(x => x.DataCriacao.Date >= inicio && x.DataCriacao.Date <= fim) .ToList();SELECT * FROM Produto WHERE DataCriacao >= '2022-01-01' AND DataCriacao <= '2022-12-31'
Produto onde a
propriedade Custo é maior que 1000.var resultado = db.Set<Produto>() .Count(x => x.Custo > 1000);SELECT Count(*) FROM Produto WHERE Custo > 1000
Custo na tabela
Produto.
var resultado = db.Set<Produto>()
.Sum(x => x.Custo);
SELECT SUM(Custo) FROM Produto
Custo na tabela
Produto.
var resultado = db.Set<Produto>()
.Min(x => x.Custo);
SELECT MIN(Custo) FROM Produto
Custo na tabela
Produto.var resultado = db.Set<Produto>() .Max(x => x.Custo);SELECT MAX(Custo) FROM Produto
Custo na
tabela Produto.var resultado = db.Set<Produto>() .Average(x => x.Custo);SELECT Average(Custo) FROM Produto
Produto pela propriedade
Codigo em ordem crescente (padrão).var resultado = db.Set<Produto>() .OrderBy(x => x.Codigo) .ToList();SELECT * FROM Produto ORDER BY Codigo
Produto pela propriedade
Codigo em ordem decrescente.var resultado = db.Set<Produto>() .OrderByDesc(x => x.Codigo) .ToList();SELECT * FROM Produto ORDER BY Codigo DESC
Produto primeiramente pela
propriedade Codigo (ascendente) e, em
seguida, pela propriedade Descricao
(ascendente) dentro dos grupos de Codigo.var resultado = db.Set<Produto>() .OrderBy(x => x.Codigo) .ThenBy(x => x.Descricao) .ToList();SELECT * FROM Produto ORDER BY Codigo, Descricao
Produto pela propriedade
Categoria e, para cada categoria, seleciona a
categoria e a soma dos custos dos produtos nessa
categoria.var resultado = db.Set<Produto>() .GroupBy(x => x.Categoria) .Select(x => new { Categoria = x.Key, CustoTotal = x.Sum(a => a.Custo) }).ToList();SELECT Categoria, SUM(Custo) as CustoTotal FROM Produto GROUP BY Categoria
Produto pelas propriedades
Categoria e Fornecedor, e para
cada combinação única, seleciona a categoria, o
fornecedor e a soma dos custos dos produtos nessa
combinação.var resultado = db.Set<Produto>() .GroupBy(x => new { x.Categoria, x.Fornecedor }) .Select(x => new { Categoria = x.Key, CustoTotal = x.Sum(a => a.Custo) }).ToList();SELECT Categoria, Fornecedor, SUM(Custo) as CustoTotal FROM Produto GROUP BY Categoria, Fornecedor
Codigo,
depois pula um certo número de registros (skip)
com base na página atual e no tamanho da página, e
finalmente pega um número específico de registros (take)
para exibir na página atual.var pagina = 3; var tamanho = 10; var skip = (pagina - 1) * tamanho; var take = tamanho; var resultado = db.Set<Produto>() .OrderBy(x => x.Codigo) .Skip(skip) .Take(take) .ToList();SELECT * FROM Produto ORDER BY Codigo OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
Pedido, Cliente
e Produto (assumindo que as
propriedades de navegação Cliente e
Produto estão definidas na entidade
Pedido). Ela seleciona a data da
transação do pedido, o nome do cliente e o código do
produto.var resultado = db.Set<Pedido>() .Select(x => new { x.DataTransacao, NomeCliente = x.Cliente.Nome, ProdutoCodigo = x.Produto.Codigo, x.Total }).ToList();SELECT s.DataTransacao, c.Nome as NomeCliente, p.Codigo as ProdutoCodigo FROM Pedido s LEFT JOIN Cliente c ON s.ClienteId = c.Id LEFT JOIN Produto p ON s.ProdutoId = p.Id
var inicio = new DateTime(2022, 1, 1); var fim = new DateTime(2022, 12, 31); var resultado = db.Set<Pedido>() .Where(x.DataTransacao >= inicio && x.DataTransacao <= fim) .GroupBy(x => new { NomeCliente = x.Cliente.Nome, ProdutoCodigo = x.Produto.Codigo }) .Select(x => new { NomeCliente = x.Key.NomeCliente, ProdutoCodigo = x.Key.ProdutoCodigo, TotalVendas = x.Sum(x.Total) }) .OrderBy(x => x.NomeCliente) .ThenByDescending(x => x.ProdutoCodigo) .ToList();SELECT c.Nome as NomeCliente, p.Codigo as ProdutoCodigo, SUM(s.Total) AS TotalVendas FROM Pedido s LEFT JOIN Cliente c ON s.ClienteId = c.Id LEFT JOIN Produto p ON s.ProdutoId = p.Id WHERE s.DataTransacao >= '2022-01-01' AND s.DataTransacao <= '2022-12-31' GROUP By c.Nome, p.Codigo ORDER BY c.Nome, p.Codigo DESC
Para consultas muito complexas envolvendo múltiplas junções e subconsultas, o SQL pode oferecer mais controle e potencial de otimização manual. No entanto, o EF Core tem evoluído bastante na tradução de LINQ para SQL eficiente.
E estamos
conversados...
"E disse-lhe Jesus: Em verdade te digo que hoje
estarás comigo no Paraíso."
Lucas 23:43
Referências:
C# - Tasks x Threads. Qual a diferença
VB .NET - Datas, horas: conceitos e operações
C# - Programação Assíncrona como : Asycn e Task
O tratamento de datas no VB.NET - Macoratti.net
C# - Obtfimo a data e a hora por TimeZone
C# - O Struct Guid - Macoratti.net
C# - Checando Null de uma forma mais elegante
DateTime - Macoratti.net
Null o que é isso ? - Macoratti.net
Formatação de data e hora para uma cultura ...
C# - Calculando a diferença entre duas datas
NET - Padrão de Projeto - Null Object Pattern
C# - Fundamentos : Definindo DateTime como Null ...
C# - Os tipos Nullable (Tipos Anuláveis)