0Pricing
C# Academy · Lección

Carga eager, lazy y explícita

Controle cuándo se cargan los datos relacionados mediante Include, ThenInclude, proxies de carga diferida y llamadas explícitas a Load.

Carga eager, lazy y explícita es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 4 lecciones en total.

Tres estrategias de carga

EF Core ofrece tres estrategias para cargar datos relacionados: carga anticipada (cargar junto con la consulta), carga diferida (cargar al acceder) y carga explícita (cargar bajo demanda). Elegir la adecuada evita el problema N+1 y los viajes innecesarios a la base de datos.

Carga anticipada con Include

La carga anticipada usa Include() para combinar los datos relacionados mediante JOIN en la misma consulta SQL. Es la estrategia más predecible y evita los problemas 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 relaciones anidadas

ThenInclude permite profundizar en el grafo de navegación. Puede cargar varios niveles en una sola 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 con filtro

EF Core 5+ permite filtrar los datos relacionados dentro de Include. Esto permite cargar un subconjunto de elementos secundarios sin realizar una consulta independiente.

// 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();

Configurar la carga diferida

La carga diferida carga automáticamente las propiedades de navegación la primera vez que se accede a ellas. Actívela instalando el paquete Microsoft.EntityFrameworkCore.Proxies y llamando a 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>();
}

La carga diferida en acción (y la trampa N+1)

La carga diferida resulta cómoda, pero es peligrosa en los bucles: cada acceso ejecuta una nueva consulta SQL, lo que provoca el problema N+1. Prefiera siempre la carga anticipada en escenarios con listas.

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();

Carga explícita

La carga explícita permite cargar una propiedad de navegación bajo demanda mediante Entry().Collection().LoadAsync() o Entry().Reference().LoadAsync(). Resulta útil cuando necesita datos relacionados de forma condicional.

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();

Carga explícita con filtro de consulta

Puede filtrar una carga explícita usando .Query() antes de llamar a LoadAsync(), lo que reduce la cantidad de datos devueltos.

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 Include extensos

Cargar varias colecciones en una sola consulta provoca una explosión cartesiana (las filas se multiplican). Utilice AsSplitQuery() para ejecutar consultas independientes para cada colección y combinarlas en memoria.

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

Proyección para evitar cargar datos de más

En lugar de cargar entidades completas con todas sus relaciones, proyecte los datos a un DTO mediante Select. Así obtendrá exactamente los datos que necesita en una sola consulta optimizada.

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

En la práctica: elegir la estrategia adecuada

Utilice esta guía de decisión en la práctica:

  • Carga anticipada + Include: siempre necesita los datos relacionados, páginas de listas
  • Proyección: vistas de solo lectura y respuestas de API — la opción más eficiente
  • Carga explícita: carga condicional según la lógica de la aplicación
  • Carga diferida: evítela en aplicaciones web; úsela solo en aplicaciones de escritorio o scripts con conjuntos de datos pequeños

Comprobación rápida

¿Qué es el problema N+1 en el contexto de la carga diferida?

Resumen: estrategias de carga

Conclusiones clave:

  • Carga anticipada (Include): carga los datos en una sola consulta — ideal para patrones de acceso predecibles
  • Include filtrado: carga solo un subconjunto de elementos secundarios — EF Core 5+
  • Carga diferida: práctica, pero arriesgada — evítela en bucles (problema N+1)
  • Carga explícita: carga bajo demanda con un control detallado
  • Proyección con Select: la opción más eficiente en escenarios de solo lectura
  • Consultas divididas: evitan la explosión cartesiana con varios Include de colecciones

Preguntas frecuentes

¿La lección «Carga eager, lazy y explícita» es gratis?

Sí — el texto completo de «Carga eager, lazy y explícita» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Carga eager, lazy y explícita»?

Controle cuándo se cargan los datos relacionados mediante Include, ThenInclude, proxies de carga diferida y llamadas explícitas a Load. Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C# Academy?

No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Carga eager, lazy y explícita»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C# Academy?

Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Carga eager, lazy y explícita
  2. SQL sin formato, procedimientos almacenados e interpolación
  3. Consultas compiladas y rendimiento
  4. Filtros de consulta globales y entidades propias
← Volver a C# Academy