EF7访问MySQL8.0时子查询Distinct/GroupBy无法翻译,SQL Server正常
EF7在MySQL与SQL Server中查询翻译差异及解决方案
环境
- MySQL 8.0
- .NET 7
- EF7
实体类代码
public class Blog { [Key] public int ID { get; set; } public string BlogName { get; set; } } public class Author { [Key] public int ID { get; set; } public string Name { get; set; } public virtual ICollection<Blog> Blogs { get; set; } }
控制器查询代码
var rt = _context .Authors .Select(a => new { a.ID, //BlogNames = a.Blogs.Select(b => b.BlogName).Distinct(),//同样报错 BlogNames = a.Blogs.GroupBy(b => b.BlogName).Select(b => b.Key) }); var lst = rt.ToList();
报错信息(中文翻译)
System.InvalidOperationException:“无法翻译LINQ表达式 'OUTER APPLY
(
SELECT b.BlogName
FROM Blogs AS b
WHERE a.ID == b.AuthorID
GROUP BY b.BlogName
) AS t'。请将查询重写为可翻译的形式,或通过插入对 'AsEnumerable'、'AsAsyncEnumerable'、'ToList' 或 'ToListAsync' 的调用显式切换到客户端计算。”
问题
为何切换为SQL Server时代码可正常运行?我需要获取包含带唯一博客名的作者列表,相同代码在SQL Server中运行正常。
原因分析
EF7针对不同数据库的LINQ查询翻译逻辑存在差异:
- SQL Server的EF提供程序支持将
GroupBy/Distinct嵌套在关联集合的投影中,能正确翻译成对应的OUTER APPLY加分组/去重的SQL语句。 - MySQL的EF提供程序(如Pomelo.EntityFrameworkCore.MySql)目前不支持这种嵌套的分组/去重翻译,无法将内存中的LINQ逻辑映射为MySQL可执行的SQL语法。
解决方案
方案1:调整查询逻辑,适配MySQL翻译规则
先对博客数据按作者ID和博客名分组去重,再与作者表关联,避免嵌套翻译问题:
var rt = from author in _context.Authors join blog in _context.Blogs .GroupBy(b => new { b.AuthorID, b.BlogName }) .Select(g => g.Key) on author.ID equals blog.AuthorID into blogGroup select new { author.ID, BlogNames = blogGroup.Select(b => b.BlogName) }; var lst = rt.ToList();
方案2:客户端计算(适合小数据量场景)
如果数据量不大,可先加载作者及其关联博客到内存,再在客户端完成去重:
var rt = _context.Authors .Include(a => a.Blogs) .AsEnumerable() .Select(a => new { a.ID, BlogNames = a.Blogs.Select(b => b.BlogName).Distinct() }); var lst = rt.ToList();
内容的提问来源于stack exchange,提问作者H.zg
相关产品推荐
相关产品推荐

