實體框架7中的多對多查詢

c# entity-framework entity-framework-core

我正在關注這個我從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; }
}

現在我的問題是如何構建我的查詢以獲得TagId的帖子?就像是:

public List<Post> GetPostsByTagId(int tagId)
{
    //linq query here
}

請記住這是EF7。

一般承認的答案

我的第一個建議是將您的集合屬性更改為ICollection<T>而不是List<T> 。你可以在這篇文章中找到一個非常好的解釋。

現在回到你真正的問題,我就是這樣做你的查詢:

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();
    }
}

你需要急於加載Post導航屬性,因為EF7不支持延遲加載,而且,正如@Igor在他的解決方案中推薦的那樣,你應該在你的上下文中包含PostTags作為DbSet

 public DbSet<PostTags> PostTags { get; set; }

說明:

您的查詢從PostTags表開始,因為在該表中您可以找到與特定標記相關的所有帖子。請參閱Include如內部聯接和Post表。如果您通過TagIdPostTagsPosts過濾之間應用連接,您將獲得所需的列。使用Select調用,您只需要Post表中的列。

如果您刪除Include呼叫,它仍然可以工作。使用Include你明確告訴你需要進行連接,但是使用Select ,EF的Linq提供者足夠聰明,可以看到它需要隱式地進行連接以獲得Posts列作為結果。


熱門答案

db.Posts.Where(post => post.PostTags.Any(pt => pt.TagId == tagId));


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因