Je suis cet exemple que j'ai obtenu de 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; }
}
Maintenant, ma question est: comment pourrais-je construire ma requête pour obtenir des publications avec TagId? Quelque chose comme:
public List<Post> GetPostsByTagId(int tagId)
{
//linq query here
}
S'il vous plaît gardez à l'esprit que c'est EF7.
Mon premier conseil est de changer les propriétés de votre collection en ICollection<T>
au lieu de List<T>
. Vous pouvez trouver une très bonne explication dans ce post .
Revenons maintenant à votre vrai problème, voici comment je ferais votre requête:
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();
}
}
Vous aurez besoin de charger avec impatience la propriété de navigation Post
car EF7 ne prend pas en charge le chargement différé et, comme @Igor le recommande dans sa solution, vous devez inclure PostTags
tant que DbSet
dans votre contexte:
public DbSet<PostTags> PostTags { get; set; }
Explication:
Votre requête commence dans la table PostTags
car elle se trouve dans cette table où vous pouvez trouver toutes les publications liées à une balise spécifique. Voir la table Include
comme une jointure interne avec Post
. Si vous appliquez une jointure entre PostTags
et Posts
filtrant par TagId
, vous obtiendrez les colonnes dont vous avez besoin. Avec l'appel Select
vous indiquez que vous n'avez besoin que des colonnes de la table Post
.
Si vous supprimez l'appel Include
, il devrait toujours fonctionner. Avec Include
vous indiquez explicitement que vous devez créer une jointure, mais avec Select
, le fournisseur Linq de EF est suffisamment intelligent pour constater qu’il doit effectuer implicitement une jointure pour obtenir les colonnes Posts
tant que résultat.