EF Core - Eager Loading


What Is Eager Loading in EF Core?

Eager loading is a data retrieval strategy in EF Core that allows you to load related entities as part of the initial database query. This technique helps reduce the number of database round-trips by retrieving all the required data in a single query, improving performance when accessing related data.


Types of Loading Strategies in EF Core

EF Core provides several strategies for loading related data. The following table summarizes the main types:

Strategy Description Use Case
Eager Loading Loads related entities as part of the initial query. When you need related data immediately.
Lazy Loading Loads related entities on demand when accessed. When related data is not always needed.
Explicit Loading Loads related entities manually by calling methods. When you need precise control over data loading.

1. Introduction to Eager Loading

Eager loading in EF Core is used to retrieve related entities as part of the initial database query. This strategy is particularly useful when you know that related data will be accessed immediately after loading the principal entity, as it can reduce the number of queries executed against the database.

        
            
var orders = _context.Orders
    .Include(o => o.Customer)
    .ToList();
        
    

This example introduces the concept of eager loading and its importance in optimizing data retrieval in EF Core.


2. Using Include Method for Eager Loading

The `Include` method in EF Core is used to specify related entities to be loaded as part of the initial query. You can use this method to load navigation properties and avoid multiple database queries.

        
            
var orders = _context.Orders
    .Include(o => o.Customer)
    .Include(o => o.OrderItems)
    .ToList();
        
    

This example demonstrates how to use the `Include` method to perform eager loading in EF Core.


3. Loading Multiple Levels of Related Data

You can use multiple `Include` and `ThenInclude` methods to load multiple levels of related data, allowing you to eagerly load complex object graphs.

        
            
var orders = _context.Orders
    .Include(o => o.Customer)
    .ThenInclude(c => c.Address)
    .Include(o => o.OrderItems)
    .ThenInclude(oi => oi.Product)
    .ToList();
        
    

This example shows how to load multiple levels of related data using `Include` and `ThenInclude` in EF Core.


4. Filtering Eager Loaded Data

In EF Core 5 and above, you can apply filters to eager-loaded data using the `Include` method, allowing you to load only the related data that meets specific criteria.

        
            
var orders = _context.Orders
    .Include(o => o.OrderItems.Where(oi => oi.Quantity > 1))
    .ToList();
        
    

This example demonstrates how to filter eager-loaded data in EF Core.


5. Using Eager Loading with Projections

You can use projections to select specific fields from related entities while performing eager loading. This helps reduce the amount of data transferred and improves performance.

        
            
var orderSummaries = _context.Orders
    .Include(o => o.Customer)
    .Select(o => new 
    {
        o.OrderId,
        CustomerName = o.Customer.Name,
        TotalAmount = o.OrderItems.Sum(oi => oi.Quantity * oi.Product.Price)
    })
    .ToList();
        
    

This example illustrates how to use projections with eager loading in EF Core.


6. Performance Considerations with Eager Loading

While eager loading can improve performance by reducing database round-trips, it can also lead to loading more data than necessary. It's important to balance eager loading with other strategies to optimize performance.

        
            
var users = _context.Users.AsNoTracking()
    .Include(u => u.UserProfile)
    .ToList();
        
    

This example provides tips for optimizing performance when using eager loading in EF Core.


7. Comparing Eager Loading with Lazy Loading

Eager loading and lazy loading are two different strategies for loading related data. Understanding the differences and when to use each can help you make better decisions in your application design.

        
            
var eagerLoadedOrders = _context.Orders
    .Include(o => o.OrderItems)
    .ToList();

var lazyLoadedOrders = _context.Orders.ToList();
foreach (var order in lazyLoadedOrders)
{
    var items = order.OrderItems;
}
        
    

This example compares eager loading with lazy loading and discusses when to use each strategy in EF Core.


8. Handling Circular References in Eager Loading

Circular references can occur when entities reference each other in a loop. EF Core provides ways to handle circular references when performing eager loading.

        
            
var employees = _context.Employees
    .Include(e => e.Manager)
    .ThenInclude(m => m.Manager)
    .ToList();
        
    

This example demonstrates how to handle circular references in eager loading in EF Core.


9. Testing Eager Loading

Testing eager loading involves verifying that related data is correctly loaded and that performance is optimized. This section covers testing strategies for eager loading.

        
            
var order = _context.Orders
    .Include(o => o.OrderItems)
    .FirstOrDefault(o => o.OrderId == 1);

Assert.NotNull(order.OrderItems);
Assert.True(order.OrderItems.Count > 0);
        
    

This example demonstrates techniques for testing eager loading in EF Core.


10. Best Practices for Eager Loading

Following best practices when using eager loading can help ensure efficient and maintainable code. Consider the following guidelines:


Summary

Eager loading in EF Core is a powerful strategy for optimizing data retrieval by loading related entities as part of the initial query. By understanding how to use eager loading effectively and balancing it with other loading strategies, developers can build performant applications that efficiently interact with relational databases.