0Pricing
C# Academy · Aula

Carregamento imediato, tardio e explícito

Controle quando os dados relacionados são carregados usando Include, ThenInclude, proxies de carregamento tardio e chamadas explícitas a Load.

Carregamento imediato, tardio e explícito é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.

Três estratégias de carregamento

EF Core oferece três estratégias para carregar dados relacionados: Carregamento antecipado (carregar junto com a consulta), carregamento tardio (carregar no acesso) e carregamento explícito (carregar sob demanda). Escolher a opção correta evita o problema de N+1 e idas e vindas desnecessárias ao banco de dados.

Carregamento antecipado com Include

O carregamento antecipado usa Include() para fazer JOIN com os dados relacionados na mesma consulta SQL. Essa é a estratégia mais previsível e evita problemas de N+1.

// Single query with JOIN
var blogs = await _db.Blogs
    .Include(b => b.Posts)
    .Where(b => b.IsActive)
    .ToListAsync();

// SQL: SELECT * FROM Blogs LEFT JOIN Posts ON ...

ThenInclude para relações aninhadas

ThenInclude avança na hierarquia de navegação. Você pode carregar vários níveis em uma única consulta.

var orders = await _db.Orders
    .Include(o => o.Customer)
    .Include(o => o.Lines)
        .ThenInclude(l => l.Product)
            .ThenInclude(p => p.Category)
    .Where(o => o.Status == OrderStatus.Pending)
    .ToListAsync();

Include com filtro

EF Core 5+ oferece suporte à filtragem de dados relacionados dentro de Include. Isso permite carregar um subconjunto de filhos sem uma consulta separada.

// Load only published posts for each blog
var blogs = await _db.Blogs
    .Include(b => b.Posts.Where(p => p.IsPublished)
                         .OrderByDescending(p => p.PublishedAt)
                         .Take(5))
    .ToListAsync();

Configuração do carregamento tardio

O carregamento tardio carrega automaticamente as propriedades de navegação na primeira vez que elas são acessadas. Habilite-o instalando o pacote Microsoft.EntityFrameworkCore.Proxies e chamando UseLazyLoadingProxies().

// 1. Install package: dotnet add package Microsoft.EntityFrameworkCore.Proxies
// 2. Enable in DbContext setup:
builder.Services.AddDbContext<AppDbContext>(opt =>
    opt.UseSqlite(connStr)
       .UseLazyLoadingProxies());

// 3. Mark navigation properties as virtual:
public class Blog
{
    public int Id { get; set; }
    public virtual ICollection<Post> Posts { get; set; } = new List<Post>();
}

Carregamento tardio em ação (e a armadilha do N+1)

O carregamento tardio é conveniente, mas perigoso em laços — cada acesso dispara uma nova consulta SQL, causando o problema de N+1. Prefira sempre o carregamento antecipado em cenários de lista.

var blogs = await _db.Blogs.ToListAsync(); // 1 query

foreach (var blog in blogs)
{
    // BAD: each access fires a new query!
    var count = blog.Posts.Count; // N queries
    Console.WriteLine(count);
}

// FIX: Use eager loading
var blogs2 = await _db.Blogs.Include(b => b.Posts).ToListAsync();

Carregamento explícito

O carregamento explícito permite carregar uma propriedade de navegação sob demanda usando Entry().Collection().LoadAsync() ou Entry().Reference().LoadAsync(). É útil quando você precisa de dados relacionados apenas em determinadas condições.

var blog = await _db.Blogs.FindAsync(1); // no posts loaded

// Load posts only when needed
if (needsPosts)
{
    await _db.Entry(blog!)
             .Collection(b => b.Posts)
             .LoadAsync();
}

// Load single reference
var post = await _db.Posts.FindAsync(99);
await _db.Entry(post!)
         .Reference(p => p.Blog)
         .LoadAsync();

Carregamento explícito com filtro de consulta

Você pode filtrar um carregamento explícito usando .Query() antes de chamar LoadAsync(), reduzindo a quantidade de dados retornados.

var blog = await _db.Blogs.FindAsync(1);

// Only load posts published this year
await _db.Entry(blog!)
         .Collection(b => b.Posts)
         .Query()
         .Where(p => p.PublishedAt.Year == DateTime.UtcNow.Year)
         .LoadAsync();

Console.WriteLine(blog!.Posts.Count);

Consultas divididas para carregamentos extensos com Include

Carregar várias coleções em uma única consulta causa uma explosão cartesiana (as linhas se multiplicam). Use AsSplitQuery() para emitir consultas separadas para cada coleção, unidas na memória.

var orders = await _db.Orders
    .Include(o => o.Lines)
    .Include(o => o.Shipments)
    .AsSplitQuery()  // 3 separate SELECTs instead of one giant JOIN
    .ToListAsync();

// Or configure globally:
opt.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);

Projeção para evitar buscar dados em excesso

Em vez de carregar entidades completas com todos os relacionamentos, faça uma projeção para um DTO usando Select. Assim, você obtém exatamente os dados necessários em uma única consulta otimizada.

var summaries = await _db.Blogs
    .Select(b => new BlogSummaryDto
    {
        Name      = b.Name,
        PostCount = b.Posts.Count(p => p.IsPublished),
        LatestPost = b.Posts
            .Where(p => p.IsPublished)
            .OrderByDescending(p => p.PublishedAt)
            .Select(p => p.Title)
            .FirstOrDefault()
    })
    .ToListAsync();
// No Include needed - translated to subqueries

Na prática: escolhendo a estratégia certa

Use este guia de decisão na prática:

  • Antecipado + Include: você sempre precisa dos dados relacionados, como em páginas de listagem
  • Projeção: exibições somente leitura e respostas de API — mais eficiente
  • Explícito: carregamento condicional com base na lógica do aplicativo
  • Tardio: evite em aplicativos web; use apenas em aplicativos de desktop ou scripts com conjuntos de dados pequenos

Verificação rápida

O que é o problema N+1 no contexto do carregamento tardio?

Recapitulação: estratégias de carregamento

Principais conclusões:

  • Carregamento antecipado (Include): carrega os dados em uma consulta — ideal para padrões de acesso previsíveis
  • Include filtrado: carrega apenas um subconjunto dos elementos filhos — EF Core 5+
  • Carregamento tardio: conveniente, mas arriscado — evite em laços (problema N+1)
  • Carregamento explícito: carrega sob demanda com controle detalhado
  • Projeção com Select: mais eficiente em cenários somente leitura
  • Consultas divididas: evitam a explosão cartesiana com vários Includes de coleções

Perguntas Frequentes

A aula “Carregamento imediato, tardio e explícito” é grátis?

Sim — o texto completo de “Carregamento imediato, tardio e explícito” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.

O que vou aprender em “Carregamento imediato, tardio e explícito”?

Controle quando os dados relacionados são carregados usando Include, ThenInclude, proxies de carregamento tardio e chamadas explícitas a Load. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C# Academy?

Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “Carregamento imediato, tardio e explícito”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C# Academy?

Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Carregamento imediato, tardio e explícito
  2. SQL bruto, procedimentos armazenados e interpolação
  3. Consultas compiladas e desempenho
  4. Filtros globais de consulta e entidades próprias
← Voltar para C# Academy