实体框架6导航集合为空而不是空 [英] Entity Framework 6 navigation collections are null instead of empty

查看:45
本文介绍了实体框架6导航集合为空而不是空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Entity Framework 6编写一个关系数据库应用程序.我有类似的类:

I'm trying to write a relational database application using Entity Framework 6. I have classes analogous to:

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; }
}

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

(OK this is a bad example because in reality you'd want each student to be in more than one subject but let's ignore this for now as it was the best example that I could think of.)

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

The problem is that, whenever there's a subject with no students, instead of subjectInstance.Students returning an empty collection it instead returns null. This means that I cannot call subjectInstance.Students.Add(studentInstance) to add the first student. I instead have to add the student separately, by calling contextInstance.Students.Add(studentInstance) after manually setting the SubjectID field on studentInstance. Once there's one or more students already associated with the subject, subjectInstance.Students is no longer null and I can add further students in the expected way.

我已经尝试过的方法:

  • 公共虚拟ICollection< Student>中删除 virtual 学生{得到;放;} -不变

  • Removing virtual from public virtual ICollection<Student> Students { get; set; } - no change

在尝试访问集合之前,先调用 contextInstance.Entry(subjectInstance).Collection("Students").Load()-可行,但很混乱并且破坏了关注点的分离(模块使用数据的人不必担心加载数据)

Calling contextInstance.Entry(subjectInstance).Collection("Students").Load() before attempting to access the collection - works but it's messy and breaks separation of concerns (the modules that work with the data shouldn't have to concern themselves with loading the data)

在创建 subjectInstance 之前,先调用 contextInstance.Subjects.Include("Students")-不变

Calling contextInstance.Subjects.Include("Students") at some point before creating subjectInstance - no change

推荐答案

作为官方文档演示,如果要防止Null引用异常,应始终在实体构造函数内部初始化集合导航属性.

As the official documentation demonstrates, you should always initialize your collection navigation properties inside the entity constructor if you want to prevent a Null reference exception.

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
}

只有在至少有一个学生的情况下,实体框架才会使用代理填充 Students 属性(否则使用属性)(如果尚未初始化,则为null).

Entity framework will fill Students property (using a proxy) only if there is at least a student, else it will leave the property as is (null if you have not initialized it).

当实体不是代理时,则只有当使用上下文的原始 entity 进行比较时,Entity Framework才在上下文中调用 SaveChanges()来跟踪其更改.此答案将进一步阐明这种行为.

When the entity is not a proxy, then Entity Framework tracks its changes only when calling SaveChanges() on the context, using its original entity state for comparison. This answer will further clarify this behavior.

这篇关于实体框架6导航集合为空而不是空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆