实体框架6导航集合为空而不是空

Mic*_*son 5 c# entity-framework-6

我正在尝试使用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; }
}
Run Code Online (Sandbox Code Playgroud)

(好吧,这是一个不好的例子,因为实际上你希望每个学生都在一个以上的学科,但现在让我们忽略它,因为这是我能想到的最好的例子.)

问题在于,只要有一个没有学生的主题,而不是subjectInstance.Students返回一个空的集合,它会返回null.这意味着我不能打电话subjectInstance.Students.Add(studentInstance)来添加第一个学生.相反,我必须contextInstance.Students.Add(studentInstance)在手动设置SubjectID字段后通过调用单独添加学生studentInstance.一旦有一个或多个学生已经与该主题相关联,subjectInstance.Students则不再为空,我可以按预期方式添加更多学生.

我已经尝试过的:

  • 删除virtualpublic virtual ICollection<Student> Students { get; set; }-无变化

  • contextInstance.Entry(subjectInstance).Collection("Students").Load()在尝试访问集合之前调用- 工作但是它很混乱并且打破了关注点的分离(与数据一起工作的模块不应该关心加载数据)

  • contextInstance.Subjects.Include("Students")在创建之前的某个时刻打电话subjectInstance- 没有变化

Fed*_*uma 9

正如官方文档所示,如果要防止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 mistakenly twice
}
Run Code Online (Sandbox Code Playgroud)

实体框架Students仅在至少有学生的情况下填充属性(使用代理),否则它将按原样保留属性(如果尚未初始化,则为null).

当实体不是代理时,实体框架仅在调用SaveChanges()上下文时使用其原始实体状态进行比较来跟踪其更改.这个答案将进一步澄清这种行为.