我正在按照从 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>
.您可以在此 post 中找到非常好的解释.
现在回到你真正的问题,这就是我如何处理你的查询:
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
的内部连接 table 。如果您在 PostTags
之间应用联接和 Posts
按 TagId
过滤,您将获得所需的列。随着Select
打电话告诉你只需要 Post
中的列 table 。
如果删除 Include
调用,它应该仍然有效。随着Include
你明确地告诉你需要做一个连接,但是使用 Select
, EF 的 Linq 提供者足够聪明,可以看到它需要隐式地进行连接才能获得 Posts
。列作为结果。
关于c# - Entity Framework 7 中的多对多查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36725543/