这真烦人
我有这样的事情:
class Person {
..properties id, name etc..
}
class Task {
..properties id, name etc..
Person Moderator {get;set}
}
public class DataModel : DbContext {
public DbSet<Task> Tasks { get; set; }
public DbSet<Person> People { get; set; }
}
然后我可以创建新任务并将People对象添加到任务并保存,我可以看到正确保存在sql后端的数据 - 保存的每个任务都保存了正确的人员ID 用它和具有该id的人也被保存回来。
但是当我尝试恢复任务时,person对象始终为null。
using (DataModel db = new DataModel()) {
Task t = db.Tasks.SingleOrDefault(p => p.Id == 22);
assert(t.Name.Lenght>0)
assert(t.Moderator != null) // always null!!!!!!
....
}
我需要做些什么才能买回整个对象图?我是否必须在SingleorDefault呼叫中加入?似乎有些不对劲。
我提到这是真的很烦人。
TIA,
答案 0 :(得分:3)
两种选择。默认情况下,代码first / dbContext模型返回一个派生自模型的代理对象(这对于了解何时遇到JSON序列化问题很重要)。代理对象使用延迟加载关联,但仅在某些情况下。必须将Moderator属性声明为virtual,以便代理可以覆盖它并为您执行延迟加载。
但是,延迟加载会产生一个名为Select N+1的问题。如果在大多数情况下您只需要Task而不是Moderator,那么这不会是一个问题。但是,如果您经常显示任务列表及其关联的主持人,除了原始列表的1之外,您将有效地为该列表中的每个任务运行额外的数据库往返(例如,对于100个任务的列表)你会做101个查询来显示任务及其主持人。)
要解决这个问题EF provides the Include operator,这会强制关系加载。这样使用
任务t = db.Tasks.Include(t =&gt; t.Moderator).SingleOrDefault(p =&gt; p.Id == 22);
希望这有帮助。
答案 1 :(得分:1)
您的Moderator
属性已关闭延迟加载,因此只有在您使用Load()
明确加载时才会加载。
您可以强制EF在您的查询中使用Include()
方法急切加载相关的Person
实体,如下所示:
Task t = db.Tasks.Include(x => x.Moderator).SingleOrDefault(p => p.Id == 22)
this article中有一个非常好的概述。