我正在尝试使用Entity Framework 6编写关系数据库应用程序。我有类似的类:
public class Subject
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
public class Student
{
public int ID { get; set; }
public int SubjectID { get; set; }
public string Name { get; set; }
public virtual Subject Subject { get; set; }
}
(好的,这是一个不好的例子,因为实际上你希望每个学生都在一个以上的学科,但现在让我们忽略它,因为这是我能想到的最好的例子。)
问题在于,只要没有学生的主题,而不是subjectInstance.Students
返回空集合,它将返回null
。这意味着我无法呼叫subjectInstance.Students.Add(studentInstance)
添加第一个学生。我需要在contextInstance.Students.Add(studentInstance)
上手动设置SubjectID
字段后拨打studentInstance
,单独添加学生。一旦有一个或多个学生已经与该主题相关联,subjectInstance.Students
不再为空,我可以按预期方式添加更多学生。
我已尝试过的内容:
从virtual
删除public virtual ICollection<Student> Students { get; set; }
- 无变更
在尝试访问集合之前调用contextInstance.Entry(subjectInstance).Collection("Students").Load()
- 工作但是很麻烦并且打破了关注点的分离(使用数据的模块不应该关心加载数据)
在创建contextInstance.Subjects.Include("Students")
之前的某个时刻致电subjectInstance
- 无变更
答案 0 :(得分:6)
如official documentation所示,如果要阻止Null引用异常,则应始终在实体构造函数中初始化集合导航属性。
public Subject()
{
Students = new HashSet<Student>(); // you may also use List<Student>, but HashSet will guarantee that you are not adding the same Student two times for mistake
}
实体框架仅在至少有学生的情况下填充Students
属性(使用代理),否则它将保留原样(如果尚未初始化,则为null)。
当实体不是代理时,实体框架仅在使用其原始实体状态进行比较时在上下文上调用SaveChanges()
时跟踪其更改。 This answer将进一步澄清这种行为。