我一直在使用一种设计模式,在使用Entity Framework Profiler之后,它看起来可能非常愚蠢。
我已经扩展了我的实体类,使其属性是与该实体关联的集合的过滤视图。像这样:
public IEnumerable<Member> ActiveMembers
{
get
{
return Members.Where(t => t.LeftDate == null);
}
}
由于我对那些没有离开俱乐部的成员感兴趣,这个属性非常有用,似乎有意义。
但是,从运行EF Profiler开始,我现在知道这通常会导致N + 1问题。如果我遍历成员并且还想显示他们的地址,那么每个地址请求都会导致额外的数据库查询。
我从question I asked知道我可以将我的财产修改为:
return Members.CreateSourceQuery().Include("Address")
.Where(t => t.LeftClubDate == null);
在这种情况下,这将摆脱N + 1问题,但我并不总是想要地址信息,我可能想要跟随会员的另一个导航属性。
理想情况下,我希望能够保持我的过滤属性(如ActiveMembers)的灵活性,并能够在之后决定要在查询中包含哪些属性。像这样:
var membersToDisplay = ActiveMembers.Include("Address").ToList();
这是可能的,还是我需要修改过滤后的属性想法?
答案 0 :(得分:3)
不,无法在Include
上致电IEnumerable
。 Include
是ObjectQuery
/ DbQuery
的一项功能。可以在Include
上调用IQueryable
(使用EFv4.1或自定义扩展),但它仍然在内部将传递的查询转发给ObjectQuery
或DbQuery
,如果强制转换则不会抛出异常完成。您必须重新设计您的应用程序。
我并不总是想要这个地址 信息,我可能想跟随 另一个导航属性 构件。
您必须根据当前需求填写数据或使用N + 1问题。例如,您可以使用单独的linq查询:
var clubId = ActiveClub.Id;
var members = (from member in context.Members.Include("Address")
where member.LeftDate == null and member.ClubId == clubId
select member).ToList();