【问题标题】:EF Core 3.0 - Convert SQL to LINQEF Core 3.0 - 将 SQL 转换为 LINQ
【发布时间】:2020-04-24 12:39:32
【问题描述】:

the blog中给出的例子有如下

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

当我们寻找完全匹配时,包含逻辑将不起作用。如果学生注册了 6 门课程(例如:1,2,3,4,5,6)并且请求的列表包含 5(例如:1,2,3,4,5),则查询将返回匹配项不应该。当学生注册了请求列表的子集时,另一种方法效果很好。

以下解决方案有效,但需要帮助将以下 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

【问题讨论】:

    标签: c# linq entity-framework-core ef-core-3.0


    【解决方案1】:

    我不知道 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());
    

    主要的匹配工作是使用All 子查询完成的。不幸的是,这对于相关链接记录多于匹配 ID 的情况来说是不够的,因此额外的计数比较可以解决这个问题。

    【讨论】:

    • AsEnumerable() 在这里不是必需的。
    • @JohnyL 它表明这不需要特殊的集合类型(数组、列表等)用于 id - 任何可枚举就足够了。
    • 太棒了,它可以工作......但只是几个小改动......new int [] 和 ToList()
    【解决方案2】:

    你可以通过这样一个简单的方法来实现它,现场演示here

    假设您通过这种方式获得了注册列表

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

    然后通过这种方式得到结果

        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);
    

    【讨论】:

    • 您根本没有使用 Enrollments 表。尝试您的解决方案得到 LINQ 错误。 @Ivan 解决方案效果很好。我接受了他/她的回答
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-14
    • 2020-03-29
    • 2023-03-17
    • 1970-01-01
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多