EF Code第一个与问题无关的实体未加载

时间:2011-07-28 17:26:30

标签: entity-framework

真烦人

我有这样的事情:

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,

2 个答案:

答案 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中有一个非常好的概述。