[英]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.