Entity Framework 7 中的多对多查询 [英] Many-to-many query in Entity Framework 7

查看:13
本文介绍了Entity Framework 7 中的多对多查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注我从 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 的帖子?类似的东西:

Now my question is how would I construct my query to get posts given TagId? Something like:

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

请记住这是 EF7.

推荐答案

我的第一个建议是将您的集合属性更改为 ICollection 而不是 List.您可以在此帖子中找到非常好的解释.

My first advice is change your collection properties to ICollection<T> instead of List<T>. You can find a really good explanation in this post.

现在回到你真正的问题,这就是我将如何做你的查询:

Now going back to your real problem, this is how I would do your query:

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:

You will need to eager load Post navigation property because EF7 doesn't support lazy loading, and also, as @Igor recommended in his solution, you should include PostTags as a DbSet in your context:

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

说明:

您的查询从 PostTags 表开始,因为在该表中您可以找到与特定标签相关的所有帖子.将 Include 视为与 Post 表的内部连接.如果您通过 TagIdPostTagsPosts 过滤之间应用连接,您将获得所需的列.通过 Select 调用,您告诉您只需要 Post 表中的列.

Your query start in PostTags table because is in that table where you can find all the post related with an specific tag. See the Include like a inner join with Post table. If you apply a join between PostTags and Posts filtering by TagId, you will get the columns that you need. With the Select call you are telling you only need the columns from Post table.

如果您删除 Include 调用,它应该仍然有效.使用 Include 您明确地告诉您需要进行连接,但是使用 Select,EF 的 Linq 提供程序足够聪明,可以看到它需要隐式执行一个连接以获取 Posts 列作为结果.

If you remove the Include call, it should still work. With the Include you're telling explicitly that you need to do a join, but with the Select, the Linq provider of EF is smart enough to see it needs to do implicitly a join to get the Posts columns as result.

这篇关于Entity Framework 7 中的多对多查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆