简体   繁体   中英

Multiple level properties with EF Core 6

After upgrading from .NET 5.0 to .NET 6.0 (including all the relative Microsoft libraries as Entity Framework), I started getting this error when executing a query to my database context using EF Core:

System.InvalidOperationException: An error was generated for warning 'Microsoft.EntityFrameworkCore.Query.NavigationBaseIncludeIgnored': The navigation 'MarkersTranslation.Marker' was ignored from 'Include' in the query since the fix-up will automatically populate it. If any further navigations are specified in 'Include' afterwards then they will be ignored. Walking back include tree is not allowed. This exception can be suppressed or logged by passing event ID 'CoreEventId.NavigationBaseIncludeIgnored' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.

This is the incriminated code:

Tour tour = await _context.Tours.Include(mpt => mpt.MarkersPerTours)
                                .ThenInclude(mrk => mrk.Marker)
                                .ThenInclude(mrkProp => mrkProp.MarkersTranslations)
                                .ThenInclude(mrk => mrk.Marker)
                                .ThenInclude(mrkTp => mrkTp.Type)
                                .FirstOrDefaultAsync(t => t.Id == tourId);

So every Tour entity has a set of related Marker with their translations, but every Marker also have a Type .

Microsoft Docs seems to approve the pattern I use for this query in order to include multiple levels.

Which is now the correct way to obtain the same result with EF Core 6?

It's interesting that this restriction "Walking back include tree is not allowed" is not in EF core 6's breaking changes list .

The way to include everything you want while only walking the tree forward is this:

Tour tour = await _context.Tours
    .Include(tour => tour.MarkersPerTours)
        .ThenInclude(mpt => mpt.Marker)
            .ThenInclude(mrk => mrk.MarkersTranslations)
    .Include(tour => tour.MarkersPerTours)
        .ThenInclude(mpt => mpt.Marker)
            .ThenInclude(mrk => mrk.Type)
    .FirstOrDefaultAsync(t => t.Id == tourId);

BTW, I changed the names of the range variables, IMO it's clearer, and more conventional, to let the names reflect their types, not the properties they're going to navigate to.

Configure warnings to ignore it as below

services.AddDbContext<YourContext>(options =>
        {
          
            options.ConfigureWarnings(warnings =>
                
            warnings.Ignore(CoreEventId.NavigationBaseIncludeIgnored));
        });

Or you can add similar things in the OnConfiguring method of Dbcontext

 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
        .ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.NavigationBaseIncludeIgnored, CoreEventId.NavigationBaseIncluded));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM