dotnet database_error ai_generated true

System.InvalidOperationException: Navigation property 'X' is null. Related data must be loaded using Include.

ID: dotnet/ef-include-ignored

Also available as: JSON · Markdown
91%Fix Rate
92%Confidence
80Evidence
2023-01-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
8 active

Root Cause

This InvalidOperationException occurs in Entity Framework Core when accessing a navigation property that was not eagerly loaded via .Include() and lazy loading is not configured. In EF Core, navigation properties are null by default unless explicitly loaded. This commonly surfaces after migrating from EF6 (which had lazy loading by default), when projecting entities without their related data, or when accessing navigation properties in serialization (JSON, AutoMapper). The fix involves adding appropriate .Include()/.ThenInclude() calls, switching to explicit projections with .Select(), or enabling lazy loading proxies if appropriate.

generic

Workarounds

  1. 93% success Add explicit .Include() and .ThenInclude() calls for all required navigation properties
    Chain Include() calls for each navigation property needed: var orders = await context.Orders.Include(o => o.Customer).Include(o => o.OrderItems).ThenInclude(oi => oi.Product).Where(o => o.Status == OrderStatus.Active).ToListAsync(); For deeply nested relationships, use ThenInclude() to traverse the chain. Create extension methods for commonly used include patterns: public static IQueryable<Order> WithFullDetails(this IQueryable<Order> query) => query.Include(o => o.Customer).Include(o => o.OrderItems).ThenInclude(oi => oi.Product);
  2. 92% success Use .Select() projections to load only the fields needed instead of full entity graphs
    Instead of loading entire entities with Include(), project to DTOs: var orderDtos = await context.Orders.Where(o => o.Status == OrderStatus.Active).Select(o => new OrderDto { Id = o.Id, CustomerName = o.Customer.Name, ItemCount = o.OrderItems.Count, Total = o.OrderItems.Sum(oi => oi.Price * oi.Quantity) }).ToListAsync(); EF Core translates the Select() expression into a single SQL query that joins only the needed tables. This avoids the Include() problem entirely and is more efficient for read-only scenarios
  3. 87% success Use AsSplitQuery() to optimize complex Include() chains that generate inefficient SQL
    When multiple collection navigations cause cartesian explosion in a single query, split them: var orders = await context.Orders.Include(o => o.OrderItems).Include(o => o.Payments).Include(o => o.ShippingHistory).AsSplitQuery().ToListAsync(); This generates separate SQL queries for each Include() and assembles results in memory, avoiding the cartesian product. Configure globally in DbContext: optionsBuilder.UseSqlServer(conn, o => o.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)); Note: split queries have different consistency guarantees than single queries

Dead Ends

Common approaches that don't work:

  1. Making the navigation property non-nullable and expecting EF Core to auto-populate it 95% fail

    EF Core does not guarantee population of navigation properties based on nullability annotations. A non-nullable reference navigation (e.g., public Order Order { get; set; } = null!;) will still be null if not loaded via Include(). The null-forgiving operator suppresses compiler warnings but does not cause EF Core to load the data. This leads to NullReferenceException at runtime instead of a clear error about missing Include()

  2. Enabling lazy loading globally by adding UseLazyLoadingProxies() to solve all missing Include() issues 70% fail

    Lazy loading introduces N+1 query problems that severely degrade performance. Each navigation property access triggers a separate database roundtrip. In list/collection scenarios, this can result in hundreds of queries instead of one. Additionally, lazy loading requires all navigation properties to be virtual, and it silently fails (returns null) when the DbContext has been disposed, such as after async operations or when entities are returned from a service layer

  3. Adding null checks around every navigation property access to prevent the exception 85% fail

    Null checks hide the fact that required related data was never loaded, leading to silent data loss and incorrect business logic. For example, if order.Customer is null because Include was missing, skipping the customer processing silently produces incomplete results. The null navigation property is a data loading bug, not a valid null state

Error Chain

Leads to:
Preceded by:
Frequently confused with: