简体   繁体   English

EF Core 3.0 - 将 SQL 转换为 LINQ

[英]EF Core 3.0 - Convert SQL to LINQ

The example given in the blog has the following 博客中给出的例子有以下内容

from e in s.StudentCourseEnrollments where courseIDs.Contains(e.Course.CourseID) select e 

The contains logic will not work when we are looking for an exact match.当我们寻找完全匹配时,包含逻辑将不起作用。 If a student has enrolled for 6 courses (ex : 1,2,3,4,5,6) and the requested list contains 5 (ex: 1,2,3,4,5) the query will return a match when it should not.如果学生注册了 6 门课程(例如:1,2,3,4,5,6)并且请求的列表包含 5(例如:1,2,3,4,5),则查询将返回匹配项不应该。 The other way works well when the student has enrolled in a subset of the requested list.当学生注册了所请求列表的子集时,另一种方法很有效。

Below solution works but need help to convert the below sql to LINQ (EF Core 3.0) ?以下解决方案有效,但需要帮助将以下 sql 转换为 LINQ(EF Core 3.0)?

Create TABLE dbo.Enrollments (StudentId INT NOT NULL, CourseId INT NOT NULL)
insert into dbo.Enrollments values (1,1)
insert into dbo.Enrollments values (1,2)
insert into dbo.Enrollments values (1,3)
insert into dbo.Enrollments values (1,4)
insert into dbo.Enrollments values (1,5)
insert into dbo.Enrollments values (1,6)

DECLARE @TempCourses TABLE
(
   CourseId INT
);

INSERT INTO @TempCourses (CourseId) VALUES (1), (2), (3),(4),(5);

SELECT t.StudentId
FROM
(
  SELECT StudentId, cnt=COUNT(*)
  FROM dbo.Enrollments
  GROUP BY StudentId
) kc
INNER JOIN
(
  SELECT cnt=COUNT(*)
  FROM @TempCourses
) nc ON nc.cnt = kc.cnt
JOIN dbo.Enrollments t ON t.StudentId = kc.StudentId
JOIN @TempCourses n ON n.CourseId = t.CourseId
GROUP BY t.StudentId
HAVING COUNT(*) = MIN(nc.cnt);

drop table dbo.Enrollments

db<>Fiddle db<>小提琴

I don't know about the SQL query, but the EF Core 3.0 LINQ query for the same task is something like this:我不知道 SQL 查询,但是对于同一任务的 EF Core 3.0 LINQ 查询是这样的:

var matchIds = new[] { 1, 2, 3, 4, 5 }.AsEnumerable();
var query = dbContext.Students
    .Where(s => s.Enrollments.All(e => matchIds.Contains(e.CourseId)) 
        && s.Enrollments.Count() == matchIds.Count());

The main matching job is done with All subquery.主要的匹配工作是通过All子查询完成的。 Unfortunately that's not enough for the case when related link records are more than the matching ids, so additional counts comparison solves that.不幸的是,当相关链接记录多于匹配的 id 时,这还不够,因此额外的计数比较解决了这个问题。

You can achieve it with a simple way like this, live demo here您可以通过像这样的简单方法来实现它,在这里进行现场演示

Let's say that you've got the list of enrollments by this way假设您通过这种方式获得了注册列表

var enrollments  = from s in dc.Students
                   from c in s.Courses
                   select new { StudentID = s.StudentID, CourseID = c.CourseID };

Then get the result by this way然后通过这种方式得到结果

    var groupedEnrollment = enrollments.GroupBy(p => p.StudentId)
                                        .Select(g => new 
                                        {
                                            StudentId = g.Key,
                                            Courses = g.Select(p => p.CourseId).ToArray() 
                                        });
    var result = groupedEnrollment.Where(g => 
                                         g.Courses.Length == courses.Length && 
                                         g.Courses.Intersect(courses).Count() == courses.Length);

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

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