实体框架6导航集合为空而不是空 [英] Entity Framework 6 navigation collections are null instead of empty
问题描述
我正在尝试使用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
frompublic 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屋!