2013-02-21 35 views
0

我与LINQ合作实体的剃刀。我有这样的事情:LINQ到EF返回所有列,而不是通过WHERE子句到服务器

@foreach(Org o in Model) { 
    @foreach(User u in o.Users.Where(x => x.Active==true)) { 
     <span> @u.FirstName </span> 
    } 
} 

当我看到SQL Server事件探查器,查询有两个主要的低效率:

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

当然,它的工作正常,但我在印象之下LINQ比这更聪明,并会发送一个更具体的查询到SQL服务器。

问:我能LINQ转嫁WHERE子句(主动==真),也只能自动获得名字列?

p.s.除非严格相关,否则我对LINQ在视图中是否是好的实践并不感兴趣 - 例如,如果视图的优化方式与编译的代码不同?

这是我的控制器代码:

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

更新 - 很多道歉,这其实是一个嵌套的循环,这可能是材料。

+0

您没有正确地处理您的数据上下文。如果您打算从您的视图访问db.Users,则不能在Controller中处理它。 – 2013-02-21 15:00:15

+0

好的 - 但这本身会影响我试图解决的问题吗? – rwalter 2013-02-21 15:30:42

+0

不,但是如果您要将'IQueryable <>'传递给视图,那么您的下一个问题就是您的DataContext超出了范围,并且EF会引发异常。 – 2013-02-22 16:29:18

回答

5

它返回用户表肯定

它所有列 - LINQ的没有你的知识,你打算使用数据 - 因此它返回的所有列。

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

我猜这是因为Model通过调用ToListAsEnumerable物化在控制器中的所有记录。

为了避免这些我将在控制器代替视图的查询和将结果传递作为模型的或在ViewData字典部分。你可以尝试查询削减下来:

var names = Model.Users.Where(x => x.Active==true) 
         .Select(u => u.FirstName) 
         .ToList(); 
ViewData["Names"] = names; 
+0

我已经发布了上面的控制器代码 - 没有ToList(),但也许是隐含的AsEnumerable,如@ Brian-Ball – rwalter 2013-02-21 15:08:25

+0

@rwalter我会在控制器中做更多的工作并适当地设置模型。理想情况下,您的“模型”应包含呈现视图所需的最少数据。如果你需要的只是'FirstName',那么你的模型可能是'IEnumerable '。 – 2013-02-21 15:37:47

+0

谢谢 - 我做了一些玩弄,发现即使是一个'@ o.Users.Count()'''SELECT * FROM Users'。这有点令人遗憾,因为我希望能够快速添加另一个字段到视图中,而无需在组合快速原型时对视图模型和映射等进行更改。 – rwalter 2013-02-21 15:46:26

2

您还没有表现出填入你的模型,其中,但是这是数据访问正在发生,就是你从数据库中检索的所有用户。

当你进入这个视图时,你已经填充了你的Users集合,所以你只是在你的内存集合中使用LINQ to Objects。

你需要改变填充模型在数据库查询级别应用过滤你的数据访问代码。

1

它可能拉的所有行的,因为无论你在呼唤ToListToArray或因Model.Users声明的类型为IEnumerable<>,而不是IQueryable<>。对扩展方法的调用被编译器重写为与常规静态方法类似,编译器使用声明的类型来确定IEnumerable<>IQueryable<>

一旦您解决了过滤问题,您可以使用Select扩展方法通过查询返回由查询返回的所有列。

+0

这听起来很有希望,但我刚刚尝试了将@model IEnumerable ;'@model IQueryable ;'改为'正确的声音'的建议',而且据我所知,它没有任何区别。我需要在控制器或模型中做些什么吗? – rwalter 2013-02-21 15:07:12