什么时候应该使用 IEnumerable,什么时候应该使用 IQueryable?

Muh*_*raz 2 .net c# linq ienumerable iqueryable

我曾多次尝试寻找差异,并且有多种答案。

众所周知的区别之一是IEnumerable从内存中过滤数据,而IQueryable在服务器端进行。

这究竟是什么意思?

对内存数据进行过滤是否仍然是服务器端的事情?

我试图在多个地方寻找它们的用途,但我无法用简单的语言找到它。

谢谢你。

Zev*_*itz 8

IEnumerable<T>表示具有获得一系列结果所需的所有信息的事物。但是,它不会公开有关如何生成序列的信息。

IQueryable<T> Expression属性中以表达式树的形式公开有关如何构造序列的信息。然后可以轻松地将此信息映射到不同的指令集。

如果您调用Enumerable.Wherean IEnumerable<T>,您将传入一个已编译的方法 -- Func<T, bool>,该方法不容易解析和翻译;不可避免地,处理此问题的唯一方法是将所有对象从服务器/提供程序/数据源加载到内存中,并在每个对象上应用已编译的方法。

如果您调用Queryable.Wherean IQueryable<T>,您将传入一个代表不同代码操作的对象 -- Expression<Func<T, bool>>。例如:

IQueryable<Person> qry = /* ... */;
qry = qry.Where(x => x.LastName.StartsWith("A"));
Run Code Online (Sandbox Code Playgroud)

编译器转换x => x.LastName.StartsWith("A")为代表其各个部分的对象:

Lambda expression, returning a `bool`
    with an `x` parameter of type `Person`
    Call the `StartsWith` method, passing in a constant string `"A"`, on
        Result of the `LastName` property, of
            the `x` element
Run Code Online (Sandbox Code Playgroud)

更多的是,调用Queryable.Where自身也会修改底层的表达式树:

Call to Queryable.Where, passing in
    The object at `qry`, and
    The previous lambda expression (see above)
Run Code Online (Sandbox Code Playgroud)

当枚举查询时(使用foreach,或调用ToList,或类似的东西),信息将被映射到另一种形式,例如 SQL:

SELECT *
FROM Persons
WHERE LastName LIKE N'A%'
Run Code Online (Sandbox Code Playgroud)

或网络请求:

http://example.com/Person?lastname[0]=a
Run Code Online (Sandbox Code Playgroud)

Queryable.Where如果可以使用构造函数以及对象和集合初始值设定项来构造表达式树,则调用后的最终表达式树将类似于此对象图:

SELECT *
FROM Persons
WHERE LastName LIKE N'A%'
Run Code Online (Sandbox Code Playgroud)

(注意。这是使用ExpressionTreeToString 库编写的。免责声明:我是作者。)