Sto seguendo questo esempio che ho ricevuto da http://ef.readthedocs.org/en/latest/modeling/relationships.html
class MyContext : DbContext
{
public DbSet<Post> Posts { get; set; }
public DbSet<Tag> Tags { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<PostTag>()
.HasKey(t => new { t.PostId, t.TagId });
modelBuilder.Entity<PostTag>()
.HasOne(pt => pt.Post)
.WithMany(p => p.PostTags)
.HasForeignKey(pt => pt.PostId);
modelBuilder.Entity<PostTag>()
.HasOne(pt => pt.Tag)
.WithMany(t => t.PostTags)
.HasForeignKey(pt => pt.TagId);
}
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public List<PostTag> PostTags { get; set; }
}
public class Tag
{
public string TagId { get; set; }
public List<PostTag> PostTags { get; set; }
}
public class PostTag
{
public int PostId { get; set; }
public Post Post { get; set; }
public string TagId { get; set; }
public Tag Tag { get; set; }
}
Ora la mia domanda è: come modifico la mia query per ottenere i post con TagId? Qualcosa di simile a:
public List<Post> GetPostsByTagId(int tagId)
{
//linq query here
}
Si prega di tenere presente questo è EF7.
Il mio primo consiglio è di modificare le proprietà della raccolta su ICollection<T>
anziché su List<T>
. Puoi trovare una spiegazione molto buona in questo post .
Tornando al tuo vero problema, ecco come farei la tua domanda:
public List<Post> GetPostsByTadId(int tagId)
{
using(var context=new MyContext())
{
return context.PostTags.Include(p=>p.Post)
.Where(pt=> pt.TagId == tagId)
.Select(pt=>pt.Post)
.ToList();
}
}
Avrai bisogno di caricare la proprietà di navigazione Post
perché EF7 non supporta il caricamento lento e inoltre, come raccomandato da @Igor nella sua soluzione, dovresti includere PostTags
come DbSet
nel tuo contesto:
public DbSet<PostTags> PostTags { get; set; }
Spiegazione:
La tua query inizia nella tabella PostTags
perché si trova in quella tabella in cui puoi trovare tutti i post relativi a un tag specifico. Vedi l' Include
come un join interno con la tabella Post
. Se applichi un PostTags
tra PostTags
e Posts
filtrando per TagId
, otterrai le colonne di cui hai bisogno. Con la chiamata Select
si sta dicendo che servono solo le colonne della tabella Post
.
Se rimuovi la chiamata Include
, dovrebbe comunque funzionare. Con l' Include
stai dicendo esplicitamente che devi fare un join, ma con Select
, il provider Linq di EF è abbastanza intelligente da vedere che ha bisogno di fare implicitamente un join per ottenere come risultato le colonne Posts
.