2014-01-23 41 views
2

下面的C#代码:差异生成的SQL

Func<Customer, bool> predicate1 = s => s.Name == "Roger"; 
dbContext.Customers.Where(predicate1); 

生成此SQL查询:

select col1,col2 from customers 

注意在上面的SQL查询,没有where子句。

然而,在此C#代码:

dbContext.Customers.Where(s => s.Name == "Roger"); 

它产生:

select col1,col2 from customers where name = 'Rogers' 

为什么不一样?是否有一种方法来传递如上所述的谓词,并仍然使用where子句生成sql查询?

+0

第一个例子不会产生任何SQL,因为你用来代替表达Func键。 Func无法解析,并且在加载所有客户后,该过滤器将在服务器端工作 –

回答

5

区别在于,在第一种情况下,您要与代表(Func<Customer, bool>)联系Enumerable.Where。 LINQ提供程序本身完全没有看到 - Enumerable.Where只会遍历整个dbContext.Customers表,并将谓词应用于进程中。

在第二种情况下,您使用expression treeQueryable.Where联系。 LINQ提供程序可以将此“代码作为数据”进行分析并将其转换为SQL。

这会做你想要什么:

Expression<Func<Customer, bool>> predicate1 = s => s.Name == "Roger"; 
dbContext.Customers.Where(predicate1); 
+0

建议的答案是我正在寻找的。谢谢。 – Jay

2

为什么不同?

在第一种情况下,您正在加载数据库中的所有数据,然后使用Enumerable.Where(Func<T, bool> predicate)进行内存过滤。

在第二种情况下,您正在调用Queryable.Where(Expression<Func<T,bool>> predicate),它被转换为SQL并在服务器端执行(lambda表达式被隐式转换为Expression<Func<T,bool>>)。

有没有办法像上面那样传递一个谓词,并仍然使用where子句生成 sql查询?

是的,你应该通过表达,而不是委托:

Expression<Func<Customer, bool>> predicate = s => s.Name == "Roger"; 
dbContext.Customers.Where(predicate); 

,只需记住 - LINQ到实体纯C#方法不能转换成SQL(和委托是一种简单的方法,只是匿名)。 Linq to Entities需要表达式树,它可以基于树中的数据分析和构建SQL查询。

+0

正确。你如何通过提交Func predicate1 = s => s.Name ==“Roger”在服务器端执行? – Jay

+0

@Jay你应该提交表达式,简单的委托不能在服务器端执行 –

+1

有道理。谢谢。 – Jay