简体   繁体   English

Migration .NET Core 2.2 to .NET Core 3.1- LINQ LEFT JOIN - Calling Take() on DefaultIfEmpty does not translate to server side SQL

[英]Migration .NET Core 2.2 to .NET Core 3.1- LINQ LEFT JOIN - Calling Take() on DefaultIfEmpty does not translate to server side SQL

I have following code in .NET CORE 2.2.After migrating entire project to .net core 3.1, it does not works in .NET 3.1.我在 .NET CORE 2.2 中有以下代码。将整个项目迁移到 .net 核心 3.1 后,它在 .NET 3.1 中不起作用。 According to This article it says DefaultIfEmpty().Take(1) will not translate to SQL.根据 这篇文章,它说DefaultIfEmpty().Take(1)不会转换为 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.DefaultIfEmpty().Take(1)
select new { students, courseDetails };

When I ran above LINQ statement I got following error.当我在 LINQ 语句上方运行时,出现以下错误。

'NavigationExpandingExpressionVisitor' failed. “NavigationExpandingExpressionVisitor”失败。 This may indicate either a bug or a limitation in EF Core.这可能表示 EF Core 中的错误或限制。 See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information.",有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2101433 。",

PS: As per the requirement I must use Take(1) . PS:根据要求,我必须使用Take(1) Because for each record in left side table right side can have multiple records.from that we will take only 1 record.因为对于左侧表中的每条记录,右侧可以有多个记录。我们将只取 1 条记录。

can anyone share suggestion to do it without breaking the LINQ Query任何人都可以在不破坏 LINQ 查询的情况下分享建议吗

I never do that in that way, I every time use First OR Default我从来没有那样做,我每次都使用First OR Default

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.FirstOrDefault()
select new { students, courseDetails };

Try next:接下来试试:

var query = from students in Students.AsQueryable().Where(e => e.StudentType == studentType)
    from courseDetails in Course.AsQueryable()
        .Where(x => x.IsActive == true)
        .Where(cd => cd.Id == students.CourseId)
        .Take(1)
        .DefaultIfEmpty()        
    select new { students, sc = courseDetails };

I don't have 3.1 installed on my machine, but 5.0 seems to translate it correctly.我的机器上没有安装 3.1,但 5.0 似乎可以正确翻译。

Your problem comes from your use of Take(1) just after DefaultIfEmpty without checking if studentCourse is actually populated or null .您的问题来自于您在DefaultIfEmpty之后使用Take(1)而没有检查studentCourse是否实际填充或null

So to avoid your NavigationExpandingExpressionVisitor you should remove your Take(1) from your left join, since the default value for a reference type is null;因此,为了避免使用NavigationExpandingExpressionVisitor ,您应该从左连接中删除Take(1) ,因为引用类型的默认值为 null; therefore, you should checks for a null reference before accessing each element of each studentCourse collection.因此,您应该在访问每个studentCourse集合的每个元素之前检查 null 引用。

It would look like this它看起来像这样

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.DefaultIfEmpty()
select new { students, courseDetails?.Take(1) ?? new CourseDetails() };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM