Whe*_*der 5 c# entity-framework entity-framework-core
我正在关注这个我从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; }
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题是如何构建我的查询以获得TagId的帖子?就像是:
public List<Post> GetPostsByTagId(int tagId)
{
//linq query here
}
Run Code Online (Sandbox Code Playgroud)
请记住这是EF7.
oct*_*ccl 10
我的第一个建议是改变你的收藏属性ICollection<T>而不是List<T>.你可以在这篇文章中找到一个非常好的解释.
现在回到你真正的问题,我会这样做你的查询:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
你需要贪婪加载Post导航属性,因为EF7不支持延迟加载,还有如@Igor在他的解决方案建议,你应该包括PostTags作为一个DbSet在你的背景:
public DbSet<PostTags> PostTags { get; set; }
Run Code Online (Sandbox Code Playgroud)
说明:
您的查询从PostTags表开始,因为在该表中您可以找到与特定标记相关的所有帖子.看到Include像Post桌子的内部联接.如果在两者之间应用连接PostTags并Posts过滤TagId,则将获得所需的列.通过Select电话,您告诉您只需要Post表格中的列.
如果您删除了Include呼叫,它仍然可以工作.由于Include你明确告诉你需要进行连接,但是使用它Select,EF的Linq提供者足够聪明,可以看到它需要隐式地进行连接以获得Posts列作为结果.