LINQ to EF返回所有列,而不是将WHERE子句传递给服务器

时间:2013-02-21 14:47:59

标签: .net asp.net-mvc linq entity-framework linq-to-entities

我正在使用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时,查询有两个主要的低效率:

  1. 返回Users表中的所有列
  2. 它返回Users表中的所有行,而不仅仅是那些具有Active == true。
  3. 的行

    当然它可以正常工作,但我的印象是LINQ比这更聪明,并且会向SQL服务器发送更具体的查询。

    问题:我可以让LINQ传递WHERE子句(Active == true),也只能自动获取FirstName列吗?

    P.S。除非严格相关,否则我对于视图中的LINQ是否是良好实践并不感兴趣 - 例如,如果视图的优化程度与编译代码不同?

    这是我的控制器代码:

    public ActionResult Index()
    {
        xyz_Entities db = new xyz_Entities();
        return PartialView(db.Orgs);
    }
    

    UPDATE - 许多道歉,这实际上是一个嵌套循环,可能是重要的。

3 个答案:

答案 0 :(得分:5)

  

它返回Users表中的所有列

确实如此 - Linq不知道你计划使用数据 - 所以它会返回所有列。

  

它返回Users表中的所有行,而不仅仅是那些具有Active == true。

的行

我猜这是因为Model通过调用ToListAsEnumerable来实现控制器中的所有记录。

为了避免这些,我会在控制器中而不是视图中进行查询,并将结果作为模型的一部分或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)

它可能会拉动所有行,因为您要么调用ToListToArray,要么因为Model.Users的声明类型是IEnumerable<>而不是IQueryable<> 。对扩展方法的调用被编译器重写,以便像普通静态方法一样被调用,编译器使用声明的类型来确定IEnumerable<> vs IQueryable<>

修复过滤问题后,您可以使用Select扩展方法确切地告诉EF您希望查询返回哪些列。