我正在使用Razor中的LINQ to Entities。我有这样的事情:
@foreach(Org o in Model) {
@foreach(User u in o.Users.Where(x => x.Active==true) ) {
<span> @u.FirstName </span>
}
}
当我查看SQL Server Profiler时,查询有两个主要的低效率:
当然它可以正常工作,但我的印象是LINQ比这更聪明,并且会向SQL服务器发送更具体的查询。
问题:我可以让LINQ传递WHERE子句(Active == true),也只能自动获取FirstName列吗?
P.S。除非严格相关,否则我对于视图中的LINQ是否是良好实践并不感兴趣 - 例如,如果视图的优化程度与编译代码不同?
这是我的控制器代码:
public ActionResult Index()
{
xyz_Entities db = new xyz_Entities();
return PartialView(db.Orgs);
}
UPDATE - 许多道歉,这实际上是一个嵌套循环,可能是重要的。
答案 0 :(得分:5)
它返回Users表中的所有列
确实如此 - Linq不知道你计划使用数据 - 所以它会返回所有列。
它返回Users表中的所有行,而不仅仅是那些具有Active == true。
的行
我猜这是因为Model
通过调用ToList
或AsEnumerable
来实现控制器中的所有记录。
为了避免这些,我会在控制器中而不是视图中进行查询,并将结果作为模型的一部分或ViewData
字典传递。您可以尝试将查询减少到:
var names = Model.Users.Where(x => x.Active==true)
.Select(u => u.FirstName)
.ToList();
ViewData["Names"] = names;
答案 1 :(得分:2)
您尚未显示模型的填充位置,但这是数据访问的发生位置,也是您从数据库中检索所有用户的原因。
当您进入此视图时,您已经填充了Users
集合,因此您只需使用LINQ to Objects和您的内存集合。
您需要更改填充模型的数据访问代码,以便在数据库查询级别应用过滤器。
答案 2 :(得分:1)
它可能会拉动所有行,因为您要么调用ToList
或ToArray
,要么因为Model.Users
的声明类型是IEnumerable<>
而不是IQueryable<>
。对扩展方法的调用被编译器重写,以便像普通静态方法一样被调用,编译器使用声明的类型来确定IEnumerable<>
vs IQueryable<>
。
修复过滤问题后,您可以使用Select
扩展方法确切地告诉EF您希望查询返回哪些列。