.NET Core 2.2迁3.1后LINQ左连接DefaultIfEmpty().Take(1)报错如何解决
问题根因
EF Core 3.1 开始取消了默认的隐式客户端评估机制,原有写法里的DefaultIfEmpty().Take(1)无法被翻译为合法的SQL语句,因此会抛出表达式访问失败的错误。
可行方案(不破坏原有LINQ结构)
方案1:交换Take和DefaultIfEmpty的调用顺序
仅调整两个方法的先后位置,即可符合EF Core的SQL翻译规则,返回结果和原有逻辑完全一致:
from students in Students.Where(e => e.StudentType == studentType) join courseDetails in Course.Where(x => x.IsActive == true) on students.CourseId equals courseDetails.Id into studentCourse from courseDetails in studentCourse.Take(1).DefaultIfEmpty() select new { students, courseDetails };
该写法会被翻译为OUTER APPLY (SELECT TOP(1) * FROM Course WHERE 匹配条件)的SQL语句,所有逻辑在数据库端执行,没有性能损耗。
方案2:使用FirstOrDefault显式取分组首条
如果不希望调整方法顺序,可以用分组首条包装为单元素集合的写法保持原有语义:
from students in Students.Where(e => e.StudentType == studentType) join courseDetails in Course.Where(x => x.IsActive == true) on students.CourseId equals courseDetails.Id into studentCourse from courseDetails in new[] { studentCourse.FirstOrDefault() } select new { students, courseDetails };
两种方案都完全满足左表每条记录仅取右表第一条匹配数据的业务要求,无需修改查询的整体结构。
内容的提问来源于stack exchange,提问作者Aslam Jiffry
相关产品推荐
相关产品推荐

