Reputation: 9655
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!
Upvotes: 1
Views: 6514
Reputation: 388023
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.
Upvotes: 15