Entity Framework 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
而不是 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
表的内部连接.如果您通过 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.
这篇关于Entity Framework 7 中的多对多查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!