Domine o EF Core: Guia Prático para Acesso a Dados
7 Erros Fatais no EF Core: Dicas Para Otimizar Consultas
Imagine que você tenha construído uma aplicação inteirinha com Entity Framework Core
🌍 Projeto: API de E-Commerce com ASP.NET Core e SQL Server!Aprenda a construir uma API robusta para e-commerce com ASP.NET Core, EF Core, JWT e Swagger, validando suas habilidades em um projeto prático real. e, quando coloca em produção, percebe que as consultas estão lerdas, travando o sistema e deixando usuários irritados. Isso pode acontecer por vários motivos, mas existem 7 erros clássicos (e mortais!) que todo mundo comete pelo menos uma vez na vida. Vamos explorar cada um, entender o porquê deles acontecerem e, claro, como corrigir e otimizar seu código para ganhar performance.
Índice🔗
- Pecado #1: Carregar o Universo com Include Exagerado
- Pecado #2: Usar Lazy Loading sem Limites (N+1 Problem)
- Pecado #3: Falta de Paginação
Projeções avançadas e uso de sort, skip e limit em consultas complexasDescubra como otimizar consultas MongoDB com projeções avançadas, sort, skip e limit em C#, garantindo performance e eficiência em aplicações .NET. e Filtros Claros - Pecado #4: Não Usar AsNoTracking quando
📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. Necessário - Pecado #5: Ignorar a Seleção de Campos Específicos (Projeção
Como Escolher o Operador Correto em Diferentes Cenários de ConsultaAprenda a selecionar os operadores LINQ ideais para filtrar, projetar, ordenar e agrupar dados, garantindo código claro e aplicação eficiente.) - Pecado #6: Falta de Índices
Utilizando índices para melhorar o desempenho em consultasTorne suas consultas MongoDB mais eficientes com C#. Descubra como índices otimizam a performance e reduzem o tempo de resposta. e Ajustes no Banco - Pecado #7: Consultas
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. Sincronas Gigantes (Esquecendo o Async)
Pecado #1: Carregar o Universo com Include Exagerado🔗
O uso abusivo do Include é um clássico. Às vezes, você quer trazer dados relacionados, mas acaba incluindo tabelas e tabelas sem nem precisar. Isso gera uma consulta
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. enorme e um “carregamento do universo”.
Exemplo de como não fazer:
var pedidos = context.Pedidos
.Include(p => p.Cliente)
.Include(p => p.Cliente.Endereco)
.Include(p => p.Itens)
.ThenInclude(i => i.Produto)
.Include(p => p.Status)
.ToList();
Se você só vai exibir na tela o nome do cliente e a data do pedido, não faz sentido trazer endereço, itens e produto
🔢 Operadores Aritméticos: Faça Cálculos como uma Calculadora Humana!Aprenda a dominar operadores aritméticos em C# com exemplos práticos, técnicas de cálculo e dicas para evitar erros e maximizar resultados.. Cada Include extra representa mais carga ao banco e
📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. ao transporte de dados.
Como Resolver:
- Traga apenas os dados que você realmente vai usar.
- Considere consultas
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. separadas quando partes dos dados são usadas em momentos diferentes.
Pecado #2: Usar Lazy Loading sem Limites (N+1 Problem)🔗
O Lazy Loading pode ser conveniente, mas é traiçoeiro: se você tem uma lista de 100 itens, e para cada item você acessa uma propriedade
⚡ Propriedades: Get e Set com Elegância (e sem Campos Privados Bagunçados)!Aprenda como utilizar propriedades em C# para encapsular dados, validar informações e manter um código organizado, seguro e de fácil manutenção. de navegação, o EF Core pode disparar 100 consultas extras (uma para cada item!), culminando no famoso “N+1 Problem”.
Exemplo de código problemático:
var pedidos = context.Pedidos.ToList();
foreach (var pedido in pedidos)
{
Console.WriteLine(pedido.Cliente.Nome);
// Aqui pode ocorrer uma query para cada pedido, se Lazy Loading estiver habilitado
}
Como Resolver:
- Use
Includequando
📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. precisar de dados relacionados de forma mais global. - Prefira carregamento explícito ou carregamento ansioso controlado se o volume de dados for
🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)Descubra como automatizar repetições em C# utilizando loops for e while com exemplos práticos que evitam erros e otimizam seu código. Aprenda mais! grande. - Fique esperto com logs de consulta para não cair em armadilhas
🧠 Memory Management Avançado: Domine Span<T> e MemoryMarshal!Transforme seu código C# usando Span<T> e MemoryMarshal para manipulação eficiente de memória, reduzindo alocações desnecessárias e elevando a performance..
Pecado #3: Falta de Paginação e Filtros Claros🔗
Trazer milhares de registros de uma só vez pode explodir sua memória e demorar um tempão. Paginar resultados e filtrar
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. com precisão ajuda muito o banco e também a aplicação a lidar melhor com os dados.
int pagina = 1;
int tamanhoPagina = 10;
var clientesPaginados = context.Clientes
.OrderBy(c => c.Nome)
.Skip((pagina - 1) * tamanhoPagina)
.Take(tamanhoPagina)
.ToList();
Com paginação, você economiza recursos do banco e do transporte de dados, além de melhorar a experiência
🌐 LinkedIn para Devs .NET: Perfil que Atrai Recrutadores!Aprenda a otimizar seu perfil LinkedIn com dicas essenciais para devs .NET. Conquiste oportunidades e destaque suas habilidades! do usuário.
Pecado #4: Não Usar AsNoTracking quando Necessário🔗
Para buscas meramente informativas (quando não há atualização de dados), o EF Core
🌍 Projeto: API de E-Commerce com ASP.NET Core e SQL Server!Aprenda a construir uma API robusta para e-commerce com ASP.NET Core, EF Core, JWT e Swagger, validando suas habilidades em um projeto prático real. não precisa manter o “tracking” de tudo em memória. Usar AsNoTracking() impede que cada objeto seja monitorado para alterações, melhorando bastante a performance
🔄 StringBuilder: Quando Concatenar Strings Vira um Pesadelo!Descubra como o StringBuilder otimiza a concatenação em C#, evitando desperdício de memória e melhorando a performance das aplicações. Veja exemplos práticos! em cenários de leitura pesada.
var produtos = context.Produtos
.AsNoTracking()
.Where(p => p.Ativo)
.ToList();
Se a ideia é só exibir dados, não tem por que manter tracking das entidades.
Pecado #5: Ignorar a Seleção de Campos Específicos (Projeção)🔗
Muitas vezes, você só quer duas ou três colunas, mas busca a entidade inteira, com dezenas de propriedades
⚡ Propriedades: Get e Set com Elegância (e sem Campos Privados Bagunçados)!Aprenda como utilizar propriedades em C# para encapsular dados, validar informações e manter um código organizado, seguro e de fácil manutenção.. O EF Core tem suporte a projeção usando Select, que evita trazer dados desnecessários.
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio.
var listaNomesPrecos = context.Produtos
.Select(p => new { p.Nome, p.Preco })
.AsNoTracking()
.ToList();
Além de reduzir o volume de dados transferidos, isso pode aliviar o tempo de retorno do banco enormemente.
Pecado #6: Falta de Índices e Ajustes no Banco🔗
Mesmo com EF Core
🌍 Projeto: API de E-Commerce com ASP.NET Core e SQL Server!Aprenda a construir uma API robusta para e-commerce com ASP.NET Core, EF Core, JWT e Swagger, validando suas habilidades em um projeto prático real., seu banco ainda precisa de uma boa modelagem e índices adequados. Se você não tiver índices nas colunas que são frequentemente usadas em Where ou
🔍 LINQ Básico: Filtre Dados como um Garimpeiro Digital!Descubra como o LINQ facilita o processamento de dados em C#. Filtre, ordene e transforme coleções com precisão e eficiência no seu código.Join, sua consulta
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. vai ser superlenta.
- Identifique colunas de pesquisa mais usadas.
- Crie índices (ou revise se o banco já criou índices
Utilizando índices para melhorar o desempenho em consultasTorne suas consultas MongoDB mais eficientes com C#. Descubra como índices otimizam a performance e reduzem o tempo de resposta. automáticos). - Monitore lentidões e use ferramentas de profiling
Ferramentas de profiling: Medindo a performance e o consumo de memória do Native AOTDescubra como otimizar apps .NET com Native AOT. Monitore CPU e memória usando dotTrace, PerfView e outras ferramentas essenciais de profiling. do próprio banco.
Pecado #7: Consultas Síncronas Gigantes (Esquecendo o Async)🔗
Em aplicações modernas, usar operações assíncronas
Repositório Assíncrono: Como Estruturar o Acesso a DadosDescubra como implementar um repositório assíncrono em C# seguindo boas práticas de separação de responsabilidades e eficiência de dados. ajuda a liberar threads enquanto espera a resposta do banco. Se você chamar .ToList() para grandes consultas
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. e não usar .ToListAsync(), pode travar a thread
Diferenças entre Threads, Tasks e Delegates em C#Aprenda as diferenças entre Threads, Tasks e Delegates em C#. Este tutorial prático ensina como otimizar a execução paralela e melhorar o desempenho. de requisição inteira, resultando em lentidão geral.
var listaProdutos = await context.Produtos
.Where(p => p.Estoque > 0)
.ToListAsync();
Com isso, seu servidor lida melhor com múltiplas requisições ao mesmo tempo e
📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. evita gargalos desnecessários.
Tracking Desnecessário: O Assassino Silencioso🔗
O Crime:
var produtos = context.Produtos.ToList(); // Tracking automático!
O EF Core rastreia todas as entidades por padrão, consumindo memória e CPU mesmo em consultas
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. de apenas leitura.
A Redenção:
var produtos = context.Produtos
.AsNoTracking()
.ToList(); // Desliga o rastreamento
Impacto: Redução de até 40% no consumo de memória
🔄 StringBuilder: Quando Concatenar Strings Vira um Pesadelo!Descubra como o StringBuilder otimiza a concatenação em C#, evitando desperdício de memória e melhorando a performance das aplicações. Veja exemplos práticos! em consultas grandes (Fonte: Microsoft Benchmarks
⏱️ Benchmark.NET: Meça a Velocidade do Seu Código!Aprenda a usar o Benchmark.NET para medir a performance de seu código com precisão. Descubra dicas, práticas confiáveis e evite erros comuns..
Select N+1: O Pesadelo das Queries Invisíveis🔗
O Crime:
var pedidos = context.Pedidos.ToList();
foreach (var pedido in pedidos)
{
// Gera uma nova query para cada pedido!
var cliente = context.Clientes.Find(pedido.ClienteId);
}
A Redenção:
var pedidos = context.Pedidos
.Include(p => p.Cliente) // Carrega tudo de uma vez
.ToList();
Dica: Use ThenInclude para
🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)Descubra como automatizar repetições em C# utilizando loops for e while com exemplos práticos que evitam erros e otimizam seu código. Aprenda mais! hierarquias complexas:
.Include(p => p.Itens)
.ThenInclude(i => i.Produto)
Consultas em Loop: Quando o Laço Vira uma Corda🔗
O Crime:
foreach (var id in idsDeClientes)
{
var cliente = context.Clientes.Find(id); // 1000 ids = 1000 queries!
}
A Redenção:
var clientes = context.Clientes
.Where(c => idsDeClientes.Contains(c.Id))
.ToList(); // 1 query para todos
Impacto: Consulta
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. com 1000 IDs: 100x mais rápido ⚡
Carregar Tudo: O Hambúrguer de 10 Andares🔗
O Crime:
var clientes = context.Clientes.ToList(); // SELECT * FROM Clientes
A Redenção:
var clientes = context.Clientes
.Select(c => new
{
c.Id,
c.Nome,
c.Email
}).ToList(); // SELECT apenas colunas necessárias
Bônus: Use DTOs para consultas
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. complexas:
public class ClienteResumoDto
{
public int Id { get; set; }
public string Nome { get; set; }
}
var clientes = context.Clientes
.Select(c => new ClienteResumoDto { /* ... */ })
.ToList();
Índices Fantasmas: A Ilusão da Performance🔗
Sintomas:
- Consultas
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. com WHERE,
🔍 LINQ Básico: Filtre Dados como um Garimpeiro Digital!Descubra como o LINQ facilita o processamento de dados em C#. Filtre, ordene e transforme coleções com precisão e eficiência no seu código.ORDER BYouJOINlentas - Planos de execução mostram "Table Scan"
Solução Mágica:
CREATE INDEX IX_Clientes_Email ON Clientes (Email);
modelBuilder.Entity<Cliente>()
.HasIndex(c => c.Email)
.IsUnique();
Regra de Ouro: Índices em colunas usadas em filtros, ordenações
🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. e joins.
Processamento em Memória: O Disfarce de Query🔗
O Crime:
var produtos = context.Produtos
.ToList() // ⚠️ Traz TUDO para a memória!
.Where(p => p.Preco > 1000);
A Redenção:
var produtos = context.Produtos
.Where(p => p.Preco > 1000) // Filtro no SQL
.ToList();
Comparação:
| Cenário | Registros no BD | Tempo |
|---|---|---|
| ToList + Where | 1.000.000 | 15s ⚠️ |
| Where + ToList | 1.000.000 | 2s ✅ |
Paginação Ingênua: O Falso Amigo🔗
O Crime:
var page1 = context.Produtos.Skip(0).Take(10).ToList();
var page2 = context.Produtos.Skip(10).Take(10).ToList();
// ...
Problema
🤝 GitHub Básico: Versionamento para Iniciantes!Descubra como o GitHub facilita colaboração, versionamento e organização de código com este tutorial prático e essencial para desenvolvedores iniciantes.: Skip fica mais lento conforme a página aumenta.
Projeções avançadas e uso de sort, skip e limit em consultas complexasDescubra como otimizar consultas MongoDB com projeções avançadas, sort, skip e limit em C#, garantindo performance e eficiência em aplicações .NET.
Solução Profissional:
var ultimoId = page1.Last().Id;
var page2 = context.Produtos
.Where(p => p.Id > ultimoId)
.Take(10)
.ToList();
Vantagem: Tempo constante ⏱️ independente da página!
Bônus: Diagnóstico de Performance
optionsBuilder.UseSqlServer(connectionString)
.LogTo(Console.WriteLine, LogLevel.Information);
2. Analise o Plano de Execução:
EXEC sp_executesql N'SELECT * FROM Clientes WHERE Id = @p0', N'@p0 int', 123
-- Clique em "Execution Plan" no SSMS
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(connectionString)
.EnableSensitiveDataLogging()
.EnableDetailedErrors());
Lembre-se: Monitorar é tão importante quanto otimizar! 🕵️♂️
No final das contas, a performance do EF Core não é uma questão mágica, mas uma soma de boas práticas
🔢 Operadores Aritméticos: Faça Cálculos como uma Calculadora Humana!Aprenda a dominar operadores aritméticos em C# com exemplos práticos, técnicas de cálculo e dicas para evitar erros e maximizar resultados. de código, design de banco e monitoramento constante. Evitar esses 7 pecados já vai te colocar em um patamar bem mais tranquilo e performático!
Autor: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.
Referências🔗
- .NET Documentation: learn.microsoft.com/pt-br/dotnet/
- Awesome .NET: github.com/quozd/awesome-dotnet
- C# Language Specification: learn.microsoft.com/pt-br/dotnet/csharp/language-reference/language-specification/
- GitHub: Microsoft/.NET: github.com/dotnet
- Microsoft Learn: C# e .NET: learn.microsoft.com/pt-br/dotnet/csharp/
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 10 months atrás
há 9 months atrás