关于c#:我真的需要在集合上使用AsQueryable()吗?

Do i really need use AsQueryable() on collection?

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List<Student> Students = new List<Student>()  
{  
    new Student(101,"Hugo","Garcia", new List<int>() { 91, 88, 76, 93 }),  
    new Student(102,"Rick","Adams", new List<int>() { 70, 73, 66, 90 }),  
    new Student(103,"Michael","Tucker", new List<int>() { 73, 80, 75, 88 }),  
    new Student(104,"Fadi","Fakhouri", new List<int>() { 82, 75, 66, 84 }),  
    new Student(105,"Peter","Barrows", new List<int>() { 67, 78, 70, 82 })  
};

var query = from student in Students
            where student.Marks.AsQueryable().All(m => m > 70)
            select student;

foreach (Student student in query)
{
    Console.WriteLine("{0} {1}<br />", student.FirstName, student.LastName);
}

但是如果我把查询改为

1
2
3
var query = from student in Students
            where student.Marks.All(m => m > 70)
            select student;

这也能产生同样的结果,那么有什么区别呢?


对于来自远程源的对象(如来自数据库的对象),需要/建议使用iqueryable。

对于内存中的集合来说,它是无用的。

在要构造表达式树时使用AsQueryable。

我能想到最适合的场景。在您的示例中,假设您需要基于学生ID的数据库中的一些信息。

现在学生在记忆库中。您需要根据学生ID启动数据库查询。

1
  var studentList = Students.Select(s => s.Id).AsQueryAble().Select(i => remoteDBProvider.GetInfo(i));

studentlist上的任何进一步操作都将从iqueryable接口(查询表达式)中调用,并且只从数据源中提取那些记录,这些记录应作为最终查询结果返回(只要数据源,本例中remoteDBProvider.GetInfo的返回值支持queryprovider)。


在您的List中,没有任何区别,因为返回的IQueryable将使用与您根本没有使用AsQueryable()相同的查询方法。

有些方法需要一个IQueryable参数。我认为AsQueryable()扩展方法对于那些场景最有用,当您需要通过一个IQueryable但只有一个IEnumerable时。

关于AsQueryable,msdn说:

If the type of source implements IQueryable,
AsQueryable(IEnumerable) returns it directly.
Otherwise, it returns an IQueryable that executes queries by
calling the equivalent query operator methods in Enumerable instead of
those in Queryable.

这意味着在您的情况下(List不实现IQueryable,您真的不需要AsQueryable


它必须完成表达式树的构建。看看这个:

AsQueryable is a method that allow the query to be converted to an
instance of IQueryable. When you use AsQueryable operator on an
existing query and apply further transformations such as applying a
filter or specifying a sort order, those lambda statements are
converted to Expression trees. Depending on the provider you are
using, expression trees will be converted into the domain specific
syntax and than executed. In the case of Linq to SQL provider, the
expression tree would be converted to SQL and executed on SQL server.
However if you use AsQueryable operator on a query that does not
implement IQueryable and only implements IEnumerable, than any
transformations that you apply on the query would automatically fall
back on IEnumerable specification. What this means is by tagging a
query with AsQueryable you get benefits of both Linq to SQL and Linq
to object implementation. If your existing query happens to implement
IQueryable, the query is converted to SQL by the Linq to SQL provider,
otherwise the query is executed in memory in the form IL code.

这里参考