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 的帖子?类似于:
public List<Post> GetPostsByTagId(int tagId)
{
//linq query here
}
请记住这是 EF7。
这并不是 EF7 特有的。
您可以扩展 DbContext 以包含 PostTags
class MyContext : DbContext
{
public DbSet<PostTags> PostTags { get; set; }
然后你的查询
db.Posts.Where(post => db.PostTags.Any(pt => pt.PostId == post.PostId && pt.TagId == tagId))
.Select(post => post);
db.Posts.Where(post => post.PostTags.Any(pt => pt.TagId == tagId));
我的第一个建议是将您的集合属性更改为 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
table 开始,因为在那个 table 中您可以找到与特定标签相关的所有 post。将 Include
视为与 Post
table 的内部联接。如果您在 PostTags
和 Posts
之间应用联接,通过 TagId
过滤,您将获得所需的列。通过 Select
调用,您告诉您只需要 Post
table 中的列。
如果删除 Include
调用,它应该仍然有效。使用 Include
你明确告诉你需要做一个连接,但是使用 Select
,EF 的 Linq 提供者足够聪明,可以看到它需要隐式地做一个连接来获得 Posts
列作为结果。
include theinclude 两者都工作正常...但唯一的问题是智能感知没有识别或显示方法只是键入然后继续所有工作正常...
var res = await _context.Diseases.Include(x => x.Disease2Symptom)
.ThenInclude(z => z.Symptom).ToListAsync();
我正在按照从 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。
这并不是 EF7 特有的。
您可以扩展 DbContext 以包含 PostTags
class MyContext : DbContext
{
public DbSet<PostTags> PostTags { get; set; }
然后你的查询
db.Posts.Where(post => db.PostTags.Any(pt => pt.PostId == post.PostId && pt.TagId == tagId))
.Select(post => post);
db.Posts.Where(post => post.PostTags.Any(pt => pt.TagId == tagId));
我的第一个建议是将您的集合属性更改为 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
table 开始,因为在那个 table 中您可以找到与特定标签相关的所有 post。将 Include
视为与 Post
table 的内部联接。如果您在 PostTags
和 Posts
之间应用联接,通过 TagId
过滤,您将获得所需的列。通过 Select
调用,您告诉您只需要 Post
table 中的列。
如果删除 Include
调用,它应该仍然有效。使用 Include
你明确告诉你需要做一个连接,但是使用 Select
,EF 的 Linq 提供者足够聪明,可以看到它需要隐式地做一个连接来获得 Posts
列作为结果。
include theinclude 两者都工作正常...但唯一的问题是智能感知没有识别或显示方法只是键入然后继续所有工作正常...
var res = await _context.Diseases.Include(x => x.Disease2Symptom)
.ThenInclude(z => z.Symptom).ToListAsync();