这是我的DataAccessLayer的工作原理:
public Foo GetFooBy(Func<Foo, bool> filter)
{
var query = from item in this.DataService.FooSet select item;
var where = query.Where(filter);
var first = where.First();
return first;
}
我假设在调用 First() 时会运行查询,但它实际上是由 Where() 执行的。从MSDN中,我意识到.Where(Func) 是由枚举定义的扩展方法,所以它是有道理的,但我不明白它与调用有什么不同。Where() 带有 lambda 表达式。
一种非常简单的方法来确定.Where() 具体化的数据是检查查询的类型、位置和第一个的类型。
- 查询是 IQueryable,这意味着数据库中尚未发生任何内容
- 其中 IEnumerable,表示数据已具体化*
- 首先是阿福
调试和 SQL 跟踪还非常清楚地表明,数据是由 .其中()
编辑 : * 可能不正确,因为 IQueryable 实现了 IEnumerable
Enumerable.Where
和 Queryable.Where
之间有一个非常重要的区别:
Enumerable.Where
需要Func<T, bool>
.
Queryable.Where
需要Expression
.
你的filter
变量不是Expression
,它是一个Func<T, bool>
,因此编译器使用Enumerable.Where
。
然后发生的情况是,FOO
表的所有行都传输到客户端,然后在内存中筛选。
正如其他人正确指出的那样,执行仍然发生在调用 First()
.
更新:
您的 SQL 跟踪无法证明具体化发生在对 Where
的调用上。它只能证明Where
的过滤没有在服务器端发生。原因在我上面的回答中得到了解释。
如何解决:
您可以通过更改方法以采用表达式来轻松解决此问题:
public Foo GetFooBy(Expression<Func<Foo, bool>> filter)
{
var query = from item in this.DataService.FooSet select item;
var where = query.Where(filter);
var first = where.First();
return first;
}
我假设查询将在调用
First()
时运行
这是一个正确的假设。
但它实际上是由
的Where()
执行
这要么是错误的,要么您没有使用System.Linq
的Where
方法。
我不明白它与使用 lambda 表达式调用
Where()
有何不同。
不是。 好吧,除非您提供了 lambda,Queryable.Where
将是执行的那个,但在这两种情况下,执行都会被推迟。
附带说明一下,可以将整个方法主体重写为:
return this.DataService.FooSet.First(filter);
它的行为会相同。