Eagerly loading multiple levels error: "The Include property lambda expression is invalid"

.net-core c# entity-framework-core

Question

I have a .NET Core 2.1 library that is leveraging Entity Framework Core v.2.2.4 with a MySQL database. I am using the code first model. I have service classes that depend on the SoarDataContext class seen below.

When I try to eagerly-load multiple-level nested entities by using the .Include() method in the way suggested in the docs, I get the following error:

"Error fetching productions: The Include property lambda expression 'p => {from Participant m in p.Participants select [m].EmergencyContacts}' is invalid. The expression should represent a property access: 't => t.MyProperty'. To target navigations declared on derived types, specify an explicitly typed lambda parameter of the target type, E.g. '(Derived d) => d.MyProperty'. For more information on including related data, see http://go.microsoft.com/fwlink/?LinkID=746393."

Here is the service method:

public async Task<IEnumerable<Production>> GetProductions()
{
    var productions = _context.Productions
        .Include(p => p.AuditionTimes)
        .Include(p => p.Participants.Select(m => m.EmergencyContacts))
        .ToList();

    return await Task.FromResult(productions);
}

My intent in the above code is to get all Productions back with all AuditionTimes "pre-fetched" and all Participants pre-fetched with all of their EmergencyContacts pre-fetched as well. Because this is the suggestion from the docs and it's blowing up the way it is seems contradictory.

FWIW, here is the class definition for my DataContext class:

using Microsoft.EntityFrameworkCore;
using Models;

namespace DataAccess
{
    public class SoarDataContext : DbContext
    {
        public SoarDataContext(DbContextOptions<SoarDataContext> options) : base(options) { }

        public DbSet<User> Users { get; set; }
        public DbSet<Participant> Participants { get; set; }
        public DbSet<ParticipantType> ParticipantTypes { get; set; }
        public DbSet<Production> Productions { get; set; }
        public DbSet<EmergencyContact> EmergencyContacts { get; set; }
        public DbSet<AuditionTime> AuditionTimes { get; set; }

        //protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        //{

        //}

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>()
                .HasIndex(u => u.Username)
                .IsUnique();

            modelBuilder.Entity<Participant>()
                .HasOne(p => p.ParticipantType);

            modelBuilder.Entity<Participant>()
                .HasIndex(p => new { p.FirstName, p.LastName, p.ProductionId })
                .IsUnique();

            modelBuilder.Entity<ParticipantType>()
                .HasIndex(pt => pt.Type)
                .IsUnique();

            modelBuilder.Entity<Production>()
                .HasMany(p => p.Participants);

            modelBuilder.Entity<Production>()
                .HasMany(p => p.AuditionTimes);

            modelBuilder.Entity<Production>()
                .HasIndex(p => new { p.Name, p.SeasonName, p.SeasonYear, p.AgeRange })
                .IsUnique();

            modelBuilder.Entity<EmergencyContact>()
                .HasOne(p => p.Participant);

            modelBuilder.Entity<AuditionTime>()
                .HasIndex(a => new { a.ProductionId, a.StartTime, a.EndTime })
                .IsUnique();

            modelBuilder.Entity<AuditionTime>()
                .HasOne(a => a.Production);
        }
    }
}

What am I missing?

EDIT: When trying the answers being suggested, I had a hard time with Visual Studio 2019's IntelliSense. For anyone running into IntelliSense suggesting you're syntax is invalid, try to compile anyways. I found it particularly confusing that the suggested answers wouldn't even compile, but it turns out IntelliSense was just giving me inaccurate errors. As mentioned in the docs:

Current versions of Visual Studio offer incorrect code completion options and can cause correct expressions to be flagged with syntax errors when using the ThenInclude method after a collection navigation property. This is a symptom of an IntelliSense bug tracked at https://github.com/dotnet/roslyn/issues/8237. It is safe to ignore these spurious syntax errors as long as the code is correct and can be compiled successfully.

1
0
7/23/2019 2:22:56 AM

Popular Answer

The initial documentation you linked to is for Entity Framework 6 while the error message links to Entity Framework Core.

Reference Loading Related Data: Including multiple levels

You can drill down through relationships to include multiple levels of related data using the ThenInclude method.

var productions = _context.Productions
    .Include(p => p.AuditionTimes)
    .Include(p => p.Participants)
        .ThenInclude(p => p.EmergencyContacts)
    .ToList();

Service method could be refactored to

public async Task<IEnumerable<Production>> GetProductions() {
    var productions = await _context.Productions
        .Include(p => p.AuditionTimes)
        .Include(p => p.Participants)
            .ThenInclude(p => p.EmergencyContacts)
        .ToListAsync();

    return productions;
}
2
7/21/2019 3:19:25 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow