【问题标题】:Compare Array of IDs Entity Framework比较 ID 实体框架的数组
【发布时间】:2015-08-13 23:58:20
【问题描述】:

我有一个简单的场景,我想编写 LINQ 查询,但我无法正确处理。这是场景:

我有 3 张桌子:

STUDENT:
    --------------------------
    SID   Name
    ---------------------
    1     Jhon
    2     Mishi
    3     Cook
    4     Steven

COURSE:
    -------------------
    CID     Name
    -------------------
    1       Maths
    2       Physics
    3       Bio
    4       CS

STUDENTCOURSE:
    ---------------------------
    SCID   SID   CID
    -----------------------
    1       1     1
    2       1     2
    3       1     4
    4       2     1
    5       2     2
    6       2     3
    7       3     1
    8       3     4
    10      4     2

对于这种情况,我想传递课程 ID 数组来查询并返回所有注册了所有这些课程的学生。我尝试了什么:

 int[] cIds = {1,2,4 };
 var result = from s in context.Students
              where s.StudentCourses.Any(sc=> cIds.Contains(sc.CID))
              select s;

但这会返回注册课程 ID 为 1、2、4 的学生。 希望你能理解我的问题。

感谢您的帮助。

【问题讨论】:

  • 如果我理解正确,您当前的查询会为您提供已注册课程 1 或 2 或 4 的任何学生的结果。您希望获得已注册所有三门课程的学生的结果?
  • 我会把它留给其他人来提出这个语句(我可以在 SQL 中轻松地做到这一点,但我的 linq 分组已经生锈了)。从 StudentCourse 中选择 SID,方法是按 SID 分组,计算 cIds 中的 CID,计数等于 cIds 的长度。
  • @AndyNichols:听起来比我的解决方案更好。 :) 干得好。
  • @T.Rahgooy 我认为我的评论仍然有效。 “counting CID where in cIds”部分意味着任何不在cIds中的课程都将被忽略。
  • @AndyNichols,是的,你说得对,我没注意到。

标签: c# asp.net entity-framework


【解决方案1】:

尝试以下方法:

int[] cIds = {1,2,4 };
var result = from s in context.Students
             where cIds.All(id => s.StudentCourses.Any(sc=> sc.CID == id))
             select s;

【讨论】:

  • 如果您的模型具有从 Student 到 Course 实体的导航(从 Student 到 Courses 而不是 Student 到 StudentCourses)或从 Student 到 StudentCourse 的导航(包含外键),则它可以完美运行。关于你的代码,我假设是最后一个。
  • 学生和学生课程之间存在密钥关系。所以 s.StudentCourses 没有问题。但是当我尝试时。它返回 0 个结果
  • 我收到 1 个结果(学生“Jhon”)。您是否将我的 where 子句准确复制到您的代码中?并且在执行查询之前是否生成了数组(如果不是硬编码)?
【解决方案2】:

使用这个:

int[] cIds = {1,2,4 };
var q = context.StudentCourses.Join(context.Students, 
                                    x => x.SId, 
                                    x => x.Id, 
                                    (sc, s) => new { Student = s, CourseId = sc.CId })
        .GroupBy(x => x.Student.Id)
        .Where(sc => cIds.All(cid => sc.Any(y => y.CourseId == cid)))
        .Select(x => x.FirstOrDefault().Student)
        .ToList();

或者如果您更喜欢 linq 查询:

int[] cIds = {1,2,4 };
var q2 = (from s in context.Students
          join sc in context.StudentCourses on s.Id equals sc.SId into sCources
          where cIds.All(id => sCources.Any(y => y.CId == id))
          select s).ToList();

这是一个fiddle,使用 linq-to-objects。

编辑:
我没有注意到在你的模型中有一个从StudentStudentCourse 的导航属性,在这种情况下查询会简单得多,不需要加入,Patrick's 的答案很完美。

【讨论】:

  • 赞赏。但我没有试一试。让我试一试,然后我会给出反馈。谢谢
猜你喜欢
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 2012-09-23
  • 2021-10-24
  • 1970-01-01
  • 2013-10-31
  • 2017-10-23
  • 1970-01-01
相关资源
最近更新 更多