Entity Framework Core shows warning message

6.2k views Asked by At

My entity classes:

public class Unit
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int? UnitID { get; set; }

    public string Name { get; set; }

    [Required]
    public int? ManufacturerID { get; set; }

    // More fields

    public Manufacturer Manufacturer { get; set; }
}

public class Manufacturer
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int? ManufacturerID { get; set; }

    public string Name { get; set; }
}

My query:

        return await DbContext.Unit.AsNoTracking().Include(r => r.Manufacturer)
                .Select(r => new
                {
                    UnitID = r.UnitID,
                    UnitName = r.Name,
                    ManufacturerName = r.Manufacturer.Name // Using Manufacturer
                }).ToListAsync();

The warning message:

...|WARN|Microsoft.EntityFrameworkCore.Query|The Include operation for navigation '[r].Manufacturer' is unnecessary and was ignored because the navigation is not reachable in the final query results. See https://go.microsoft.com/fwlink/?linkid=850303 for more information...

I am using Manufacturer.name in new anonymous so It means navigation [r].Manufacturer must be used.

Why Entity Framework Core warns the message? Is am doing wrong? Thanks!

1

There are 1 answers

5
poke On BEST ANSWER

This is actually a common misconception about what Entity Framework’s Include actually does. It actually does not affect the filtering at all but is only relevant when the result is materialized.

When you do something.Include(x => x.Prop) then what you are actually telling Entity Framework is this: When there is an entity of the type of something in the result, then also include the entity that is reachable by the navigation property Prop.

For example, following the usual blogs & posts example that the EF Core documentation uses, context.Blogs.Include(blog => blog.Posts) will load the Blog entities and include the related Posts for each Blog entity. But this matters only if you actually select Blog entities in the result.

context.Blogs
    .Select(blog => new {
        Id = blog.BlogId,
        Url = blog.Url,
    });

This query for example does not produce any Blog entities, so includes on the Blog entity would be ignored. You could also expand this query to also include information about the posts, without actually having to include the Posts navigation property on the Blog entity. Since there’s no Blog entity in the result, that wouldn’t have any effect:

context.Blogs
    .Select(blog => new {
        Id = blog.BlogId,
        Url = blog.Url,
        PostCount = blog.Posts.Count(),
    });

Note that not including a navigational property does not prevent you from using it to filter something:

context.Blogs
    .Where(blog => blog.Posts.Any(post => title == "Foo"));

This would select all Blog entities that contained a post with a title “Foo”; but the Posts navigation property wouldn’t be loaded since it wasn’t included in the query. But you can still filter by it.


So .Include() will only affect the result of the query, and only if there is an actual entity of that type being produced. It is however not necessary to include something just to filter by it.

In your particular example, since there isn’t any Unit entity in the result, the inclusion of Unit.Manufacturer has no effect. And in order to add the Unit.Manufacturer.Name to the result, you do not need to include the navigation property.