实体框架7中的多对多查询 [英] Many-to-many query in 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< 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屋!