Le mie classi di entità:
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; }
}
La mia domanda:
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();
Il messaggio di avviso:
... | WARN | Microsoft.EntityFrameworkCore.Query | L'operazione Includi per la navigazione '[r] .Manufacturer' non è necessaria ed è stata ignorata perché la navigazione non è raggiungibile nei risultati della query finale. Vedere https://go.microsoft.com/fwlink/?linkid=850303 per ulteriori informazioni ...
Sto usando Manufacturer.name in un nuovo anonimo quindi Significa navigazione [r]. Il produttore deve essere utilizzato.
Perché Entity Framework Core avverte il messaggio? Sto sbagliando? Grazie!
Questo è in realtà un malinteso comune su ciò che realmente Include
Entity Framework. In realtà non influisce affatto sul filtro ma è rilevante solo quando il risultato è materializzato.
Quando fai something.Include(x => x.Prop)
allora quello che stai effettivamente dicendo a Entity Framework è questo: quando c'è un'entità del tipo di something
nel risultato, allora includi anche l'entità che è raggiungibile dalla navigazione proprietà Prop
.
Ad esempio, seguendo il solito esempio di blog e post che utilizza la documentazione EF Core, context.Blogs.Include(blog => blog.Posts)
caricherà le entità Blog
e includerà i Posts
correlati per ciascuna entità Blog
. Ma questo è importante solo se si selezionano effettivamente le entità Blog
nel risultato.
context.Blogs
.Select(blog => new {
Id = blog.BlogId,
Url = blog.Url,
});
Questa query, ad esempio, non produce alcuna entità Blog
, quindi le Blog
sull'entità Blog
verrebbero ignorate. È inoltre possibile espandere questa query per includere anche informazioni sui post, senza effettivamente includere la proprietà di navigazione Posts
nell'entità Blog
. Dal momento che non ci sono entità Blog
nel risultato, ciò non avrebbe alcun effetto:
context.Blogs
.Select(blog => new {
Id = blog.BlogId,
Url = blog.Url,
PostCount = blog.Posts.Count(),
});
Nota che non includere una proprietà di navigazione non ti impedisce di usarla per filtrare qualcosa:
context.Blogs
.Where(blog => blog.Posts.Any(post => title == "Foo"));
Ciò selezionerebbe tutte le entità Blog
che contenevano un post con un titolo "Foo"; ma la proprietà di navigazione Posts
non verrebbe caricata poiché non era inclusa nella query. Ma puoi ancora filtrarlo.
Quindi .Include()
influenzerà solo il risultato della query e solo se viene prodotta un'entità effettiva di quel tipo. Non è tuttavia necessario includere qualcosa solo per filtrarlo.
Nel tuo esempio particolare, poiché non vi è alcuna entità Unit
nel risultato, l'inclusione di Unit.Manufacturer
. Il Unit.Manufacturer
non ha alcun effetto. E per aggiungere Unit.Manufacturer.Name
al risultato, non è necessario includere la proprietà di navigazione.