.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)