代码之家  ›  专栏  ›  技术社区  ›  Chris Becke

对EF核心中的多对多关系执行有效查询

  •  1
  • Chris Becke  · 技术社区  · 6 年前

    在实体框架核心中,可以设置 many-to-many 通过联接表的关系。

    我不知道如何有效地查询这样的关系。考虑到下面的参考关系,我有, Post 实体与 PostTags 集合为空。我想把所有的 Tag 与关联的 到目前为止,我所拥有的最好的东西是这样的:

    void GetAllTags(Post somePost)
    {
        await dbContext.Entry(somePost)
            .Collection(p => p.PostTags)
            .LoadAsync();
        foreach(var postTag in somePost.PostTags)
        {
            await dbContext.Entry(postTag)
                .Reference(p => p.Tag)
                .LoadAsync();
        }
    }
    

    我真的想退回 ICollection<Tag> 通过对数据库的单个查询。


    这是来自的参考实现 Relationships - EF Core | Microsoft Docs

    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; }
    }
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   Ivan Stoev    6 年前

    如果你只需要 得到 与post关联的标记列表,可以使用简单的投影查询。一定要从一开始 DbSet<> (EF核心) IQueryable<> )而不是物化的对象/集合,例如

    ICollection<Tag> GetAllTags(Post somePost)
    {
        return await dbContext.Set<PostTag>()
            .Where(pt => pt.PostId == somePost.PostId)
            .Select(pt => pt.Tag)
            .ToListAsync();
    }
    

    如果你真的想 负载 他们进入关口 Post 实体实例,您可以通过 Query 方法:

    void LoadAllTags(Post somePost)
    {
        await dbContext.Entry(somePost)
            .Collection(p => p.PostTags)
            .Query()
            .Include(pt => pt.Tag)
            .LoadAsync();
    }