Entity Framework Core deve ancora implementare relazioni molti-a-molti, come tracciato nel numero di GitHub # 1368 ; tuttavia, quando seguo gli esempi di navigazione in quel numero o le risposte simili qui a Stack Overflow, la mia enumerazione non riesce a dare risultati.
Ho una relazione molti-a-molti tra Foto e Tag.
Dopo aver implementato la tabella di join, gli esempi mostrano che dovrei essere in grado di:
var tags = photo.PhotoTags.Select(p => p.Tag);
Mentre ciò non produce risultati, sono in grado di caricare tramite:
var tags = _context.Photos
.Where(p => p.Id == 1)
.SelectMany(p => p.PhotoTags)
.Select(j => j.Tag)
.ToList();
Codice pertinente:
public class Photo
{
public int Id { get; set; }
public virtual ICollection<PhotoTag> PhotoTags { get; set; }
}
public class Tag
{
public int Id { get; set; }
public virtual ICollection<PhotoTag> PhotoTags { get; set; }
}
public class PhotoTag
{
public int PhotoId { get; set; }
public Photo Photo { get; set; }
public int TagId { get; set; }
public Tag Tag { get; set; }
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<PhotoTag>().HasKey(x => new { x.PhotoId, x.TagId });
}
Cosa mi manca da altri esempi?
In realtà questo non è uno specifico per la relazione many-to-many
, ma in generale per la mancanza del supporto per il caricamento lazy in EF Core. Quindi, per avere la proprietà Tag
popolata, deve essere caricata (o esplicitamente) desiderosa. Tutto questo è (sorta) spiegato nella sezione relativa ai dati relativi al caricamento della documentazione di EF Core. Se dai un'occhiata alla sezione Includere più livelli , vedrai la seguente spiegazione
È possibile eseguire il drill down delle relazioni per includere più livelli di dati correlati utilizzando il metodo
ThenInclude
. Nell'esempio seguente vengono caricati tutti i blog, i relativi post correlati e l'autore di ciascun post.
ed esempio per caricare Post.Author
che è praticamente uguale al tuo:
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToList();
}
Quindi per farlo funzionare
var tags = photo.PhotoTags.Select(p => p.Tag);
la variabile photo
avrebbe dovuto essere recuperata usando qualcosa di simile a questo:
var photo = _context.Photos
.Include(e => e.PhotoTags)
.ThenInclude(e => e.Tag)
.FirstOrDefault(e => e.Id == 1);