EF Core 2.x中使用Include仍出现N+1查询问题求助
EF Core 2.x中Include关联仍出现N+1查询的原因
问题背景
我们拥有Blogs和Comments两张表,Blogs与Comments为一对多关系。现有一个接收博客ID列表作为参数的方法,需返回博客基础信息及其关联评论。最初实现时已使用Include关联Comments,但EF Core 2.x仍生成N+1查询。当前环境为.NET 4.7.x,因使用WCF服务无法升级版本,最终采用了一种不够高效但可用的替代实现,现需明确原代码出现N+1问题的原因。
最初实现代码
public List<BlogDto> GetAllBlogs(List<long> blogIds) { var query = from blogId in blogIds join blog in dbContext.Blogs.Include(blog => blog.Comments) on blogId equals blog.Id select new BlogDto() { Id = blog.Id, Name = blog.Name, // ... 其他属性 // Comments prop is List<CommentDto> Comments = blog.Comments.Select(comment => new CommentDto { Id = comment.Id, Content = comment.Content }).ToList() }; return query.ToList(); }
原代码出现N+1查询的原因
- Include被投影操作忽略:EF Core 2.x的
Include方法仅作用于将关联数据加载到原始实体对象中,而你在查询中直接通过select new BlogDto()进行投影映射,此时EF Core会忽略Include指令——它认为你不需要加载完整的Blog实体(包括关联的Comments),只需要投影指定的属性,因此不会主动将Comments关联数据一次性查询出来。 - 投影内的ToList()触发单条查询:在DTO的
Comments属性赋值时,你调用了blog.Comments.Select(...).ToList(),这会导致EF Core在获取每个Blog实体后,单独发送一条SQL查询去获取该Blog对应的Comments数据。最终形成1条查询获取所有Blog,加上N条查询分别获取每个Blog的评论,也就是N+1查询。
替代实现代码
public List<BlogDto> GetAllBlogs(List<long> blogIds) { var blogQuery = from blogId in blogIds join blog in dbContext.Blogs on blogId equals blog.Id select new BlogDto() { Id = blog.Id, Name = blog.Name, // ... 其他属性 }; var comments = (from blog in blogQuery join comment in dbContext.Comments on blog.Id equals comment.BlogId select new CommentDto { Id = comment.Id, Content = comment.Content, BlogId = blog.Id }).GroupBy(c => c.BlogId).ToDictionary(v => v.Key, v => v.ToList()); var blogList = blogQuery.ToList(); blogList.ForEach(b => { if (comments.ContainsKey(b.Id)) { b.Comments = comments[b.Id]; } }); return blogList; }
内容的提问来源于stack exchange,提问作者abdismoz
相关产品推荐
相关产品推荐

