使用LINQ to entity覆盖匿名类型的延迟加载

时间:2015-04-26 19:09:50

标签: linq entity-framework

我有三个由Entity Framework生成的实体。一个是event,其中包含名为frogsuser_bookings的导航属性。我之前发布了一个相关的问题,关于执行一个似乎有效的子查询,但它阻止我覆盖一个属性的延迟加载。

var evts = from evt in context.events.Include("frogs")
           where evt.event_id < 10
           select evt;

这样做 - 导航属性frogs被加载。

但是,当我将LINQ更改为:

var evts = from evt in context.events.Include("frogs")
           where evt.event_id < 10
           select new
           {
               Event = evt,
               HasBooked = evt.user_bookings.Any(x => x.user_id == 1)
           };

尝试访问frogs时出错,因为ObjectContext不再存在。我尝试从event类的类定义中删除虚拟,但这只会导致一个空的青蛙列表,当它们肯定在那里时!

1 个答案:

答案 0 :(得分:3)

这是by design。如果查询结果是投影,则忽略Include即使投影包含可能包含Include d属性的实体。

我不知道为什么EF会这样实现它。如果投影不包含任何实体,但只是某种类型(匿名或非匿名),则没有Include目标,因此忽略它是有道理的。但是,如果投影确实包含Include目标(在您的情况下为Event),那么在我看来,他们本可以决定做出这样的工作。但是,嗯,他们没有。

也许是因为Include实际上有效的规则是less obvious than you might expect。在您的情况下,查询的形状会在Include之后发生变化,因此会被忽略。

您还可以通过查询frogs

解决此问题
from evt in context.events.Include("frogs")
where evt.event_id < 10
select new
{
   Event = evt,
   Frogs = evt.frogs,
   HasBooked = evt.user_bookings.Any(x => x.user_id == 1)
};

现在每个Event也会填充frogs个集合(因为关系修正)。但有两个陷阱。这些集合未被标记为已加载,因此 -

  • 如果之后可能发生延迟加载,则会发生这种情况,使初始加载无效。
  • 如果延迟加载不再发生(因为上下文已被处理),您将获得例外。

这意味着要完成这项工作,您必须禁用延迟加载。