关于C#:将IQueryable linq查询转换为IEnumerable 取消linq优化的工作方式?

Convert an IQueryable linq query to IEnumerable<T> cancels out linq optimized way to work?

我在.NET上有点新手,我想知道Linq是如何工作的,因为您可以一个接一个地应用许多Linq查询,但在它们被用于传输信息或转换为列表等之前,它们都不会真正执行。
使用IQueryable有两种重要的方法来获取LINQ查询,这两种方法适用于直接在SQL上使用where过滤器,以及IEnumerable,后者获取所有记录,然后在内存上使用它们。但是,让我们看看这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
            //Linq dynamic library
            IQueryable<Table> myResult = db.Categories
                .Where(a => a.Name.Contains(StringName))
                .OrderBy("Name")
                .Skip(0)
                .Take(10);

            if (myResult != null)
            {
                return myResult.AsEnumerable();
            }
            else
            { return null; }

depsite我使用的是linq动态库,这个查询的直接结果是get on IQueryable,如果查询最终返回为IEnumerable,那么这个查询是否真的是在sql上过滤的?还是在记忆中?


不用担心,它仍将在数据库中执行。基本上,这都取决于使用Where等的实现。当您通过Queryable扩展方法调用IQueryable上的方法时,它将使用表达式树。当您开始从该查询中提取时,它将转换为SQL并发送到数据库。

另一方面,如果将这些方法中的任何一个作为IEnumerable使用(就编译时类型而言),那么它将使用Enumerable中的扩展方法,并且所有其余的处理都将在进程中完成。

举个例子,考虑一下:

1
2
3
4
var query = db.People
              .Where(x => x.Name.StartsWith("J"))
              .AsEnumerable()
              .Where(x => x.Age > 20);

这里,AsEnumerable()只返回其输入序列,但键入IEnumerable。在这种情况下,数据库查询只返回名称以J开头的人,然后在客户机上进行年龄筛选。


如果返回一个IEnumerable,然后进一步优化查询,那么进一步的优化将在内存中进行。在IQueryable上表示的部分将被转换为适当的SQL语句(显然,对于linq-to-sql的情况)。

请参阅返回IEnumerable与iqueryable以获得更长更详细的答案。