繁体   English   中英

如何使此查询在Entity Framework Code First CTP5上运行

[英]How to make this query work on Entity Framework Code First CTP5

我有以下模型(为这个问题愚蠢):

public class Student
{
    public int ID { get; set; }
    public virtual ICollection<StudentCourse> StudentCourses { get; set; }

     public Student(){
        StudentCourses = new List<StudentCourse>();
    }
}

public class StudentCourse
{
    public int ID { get; set; }
    public string Grade { get; set; }
    public int StudentID { get; set; }
    public int CourseID { get; set; }

    public virtual Student Student { get; set; }
    public virtual Course Course { get; set; }
}

public class Course
{
    public int ID { get; set; }        
    public virtual ICollection<StudentCourse> StudentCourses { get; set; }

    public Course() {
        StudentCourses = new List<StudentCourse>();
    }
}

一切都在我的DbContext类中链接并按预期工作。 我想找到所有参加过课程的学生,所以我这样做:

var query = db.Students
            .Where(s => s.StudentCourses.Course.ID == 11); 

但它失败了,因为由于某种原因,EF无法看到StudentCourse和Course之间的链接。 错误消息是:

'System.Collections.Generic.ICollection'不包含'Course'的定义,也没有扩展方法'Course'接受类型为'System.Collections.Generic.ICollection'的第一个参数'(你是否缺少using指令)或汇编参考?)。

但是以下工作正常:

var query = db.StudentCourses
            .Where(s => s.Course.ID == 11)
            .Select(s=>s.Students);

这是一个错误还是我做错了什么?

StudentCourses是一个课程列表,您无法使用.Course访问单个课程。 为了做到这一点,你需要使用一个适用于单个记录的子句,例如select,where,any等。(大多数采用lambda表达式的IEnumerable扩展都是为了这个目的。)

var query = db.Students.Where(s => s.StudentCourses.Any(r => r.Course.CourseID == 11)); 

如果你想在db.Students上工作,那很好,但你发布的第二个例子可能在语义上更接近于你正在做的事情。 学生课程代表学生和课程之间的联系。 您的where子句限制为特定课程,select子句将学生课程集合投射到其关联的学生。

为什么这部分在你的代码中:

public Student(){
    StudentCourses = new List<StudentCourse>();
}

当我这样做时,我不需要包括那个部分,它只是有效

public virtual ICollection<StudentCourse> StudentCourses { get; set; }

一个人。 您通过提前分配清单来阻止内部准备工作。


请注意

var query = db.Students
              .Where(s => s.StudentCourses.Course.ID == 11);

不一定有效,因为StunderdCourses可能会被懒惰地评估,你会想要使用:

var query = db.Students
              .Include("StudentCourses")
              .Where(s => s.StudentCourses.Course.ID == 11);

这将确保每个学生的学生课程也包含在查询中。


请注意,上述查询效率低,因为您要获取所有学生,并且对于每个学生您正在获取所有课程,您最后建议的代码要好得多,因为它首先查找正确的课程然后找到属于的学生它:

var query = db.StudentCourses
              .Include("Course")
              .Where(s => s.Course.ID == 11)
              .Select(s=>s.Students);

请注意再次使用Include ,这对于进行延迟评估的服务器是必需的。


但是,请注意,该类实际上具有CourseID属性,因此您还可以执行以下操作:

var query = db.StudentCourses
              .Where(s => s.CourseID == 11)
              .Select(s=>s.Students);

暂无
暂无

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

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