我有像这样的课程,学生和老师
public class Course
{
[Key, DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid CourseId { set; get; }
public ICollection<Student> Students { set; get; }
public Teacher Teacher { get; set; }
}
public class Student
{
[Key, DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid StudentId { set; get; }
public ICollection<Course> Courses { set; get; }
}
public class Teacher
{
[Key, DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid TeacherId { get; set; }
public ICollection<Course> Courses { get; set; }
}
我正在尝试通过主键获取课程,如下所示
Course c = _unitOfWork.DbContext.Set<Course>().Find(keyValue);
我从数据库中获取课程对象,但课程的学生和教师属性为空
我错过了什么? 感谢
答案 0 :(得分:13)
Find
正常工作,因为EF从不加载相关实体本身。要加载相关属性,您必须使用预先加载或延迟加载。第三种选择有时被称为显式加载。
延迟加载将为您提供相关实体的自动加载,但它会为数据库生成其他查询。首次访问该属性时,将加载相关实体或相关集合。要使用延迟加载,您必须将实体中的所有导航属性标记为virtual
(@ckal为您提供了示例)。此外,只有在用于加载主实体的上下文仍然存在时,延迟加载才有效。
预先加载将定义哪个关系必须与主实体一起加载。急切加载由Include
方法执行。您可以将Find
重写为:
Course c = _unitOfWork.DbContext
.Set<Course>()
.Include(c => c.Students)
.Include(c => c.Teacher)
.SingleOrDefault(c => c.CourseId == keyValue);
显式加载将允许您明确说明应该加载某些关系。您甚至可以为加载相关实体定义一些条件,这是其他两种方法无法实现的。您必须先加载主实体,然后在处理上下文之前,您可以执行以下操作:
context.Entry(course).Collection(c => c.Students).Load();
答案 1 :(得分:4)
将virtual
添加到导航属性以启用延迟加载。
public class Course
{
[Key, DatabaseGenerated(DatabaseGenerationOption.Identity)]
public Guid CourseId { set; get; }
public virtual ICollection<Student> Students { set; get; }
public virtual Teacher Teacher { get; set; }
}