我一直在使用 Entity Framework Profiler 来测试 MVC 项目中的数据访问,并且遇到了几个页面,其中由于 N+1 问题,我进行的数据库查询远多于我需要的数量。
这是一个简单的例子来说明我的问题:
var club = this.ActiveClub; // ActiveClub uses code similar to context.Clubs.First()
var members = club.Members.ToList();
return View("MembersWithAddress", members);
该视图循环遍历成员,然后遵循每个成员的导航属性来显示他们的地址。每个地址请求都会导致额外的数据库查询。
解决此问题的一种方法是使用 Include 来确保预先查询我需要的额外表。但是,我似乎只能在直接附加到上下文的俱乐部对象集上执行此操作。在这种情况下,ActiveClub 属性由许多控制器共享,我并不总是想预先查询成员和地址表。
我希望能够使用类似的东西:
var members = club.Members.Include("Address").ToList();
但是,Members 是一个 EntityCollection,并且没有 Include 方法。
有没有办法强制加载 Members EntityCollection 并要求 EF 也加载其地址?
或者,以这种方式在实体上使用 EntityCollection 导航属性,只是一个非常糟糕的主意;当你从上下文中获取它时,你应该知道你正在加载什么?
如果您的实体继承自EntityObject
尝试使用这个:
var members = club.Members.CreateSourceQuery()
.Include("Address")
.ToList();
如果您将 POCO 与延迟加载代理一起使用,请尝试使用以下命令:
var members = ((EntityCollection<Club>)club.Members).CreateSourceQuery()
.Include("Address")
.ToList();
显然第二个版本不是很好,因为 POCO 用于消除对 EF 的依赖,但现在您需要将集合转换为 EF 类。另一个问题是查询将被执行两次。延迟加载将触发Members
一次访问该属性,然后当您调用时将执行第二个查询ToList
。这可以通过以下方式解决关闭延迟加载在运行查询之前。
当你说ActiveClub
是共享的,我相信这意味着它是派生控制器中使用的基本控制器中的属性。在这种情况下,您仍然可以在不同的控制器中使用不同的代码来填充属性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)