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

查看:39
本文介绍了实体框架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< T> ,而不是 List< T> .您可以在此帖子中找到一个很好的解释.

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

由于EF7不支持延迟加载,因此您需要急于加载 Post 导航属性,并且,如@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 的内部联接的表.如果在通过 TagId 过滤的 PostTags Posts 之间应用联接,您将获得所需的列.通过 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.

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

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