我真的需要在集合上使用AsQueryable()吗?
我真的需要在集合上使用AsQueryable()吗?
示例代码:\n
ListStudents = new List () { new Student(101, "Hugo", "Garcia", new List () { 91, 88, 76, 93 }), new Student(102, "Rick", "Adams", new List () { 70, 73, 66, 90 }), new Student(103, "Michael", "Tucker", new List () { 73, 80, 75, 88 }), new Student(104, "Fadi", "Fakhouri", new List () { 82, 75, 66, 84 }), new Student(105, "Peter", "Barrows", new List () { 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}", student.FirstName, student.LastName); }
\n但是如果我将查询更改为:\n
var query = from student in Students where student.Marks.All(m => m > 70) select student;
\n这也能正常工作并产生相同的结果,那么有什么区别呢?
在使用LINQ进行查询时,有时会遇到需要将一个集合转换为`IQueryable`的情况。而`AsQueryable()`方法就是用来实现这一转换的。当我们在一个已有的查询中使用`AsQueryable()`方法,并对其进行进一步的转换,比如应用筛选条件或者指定排序顺序时,这些Lambda表达式将会被转换为表达式树。根据所使用的提供程序的不同,表达式树将被转换为特定于领域的语法,然后执行。在使用Linq to SQL提供程序的情况下,表达式树将被转换为SQL并在SQL服务器上执行。然而,如果我们在一个只实现了`IEnumerable`而没有实现`IQueryable`的查询上使用`AsQueryable()`方法,那么应用在查询上的任何转换都将自动回退到`IEnumerable`规范。这意味着,通过在查询上使用`AsQueryable`方法,我们既可以享受到Linq to SQL的优势,也可以享受到Linq to Object的实现。如果我们的现有查询已经实现了`IQueryable`,那么该查询将由Linq to SQL提供程序转换为SQL,否则该查询将以IL代码的形式在内存中执行。
解决方法:对于一个已有的查询,如果我们想要在其上应用进一步的转换,同时又希望利用Linq to SQL和Linq to Object的优势,我们可以使用`AsQueryable()`方法将其转换为`IQueryable`类型的查询。这样一来,不管该查询是实现了`IQueryable`还是`IEnumerable`,我们都可以对其进行进一步的转换操作,而不会受到`IEnumerable`规范的限制。
在你的List<Student>
的情况下,使用AsQueryable()
并没有任何区别,因为返回的IQueryable<T>
将使用与没有使用AsQueryable()
时相同的查询方法。一些方法期望一个IQueryable<T>
参数。我认为AsQueryable()
扩展方法在那些需要传递IQueryable<T>
但只有IEnumerable<T>
的情况下非常有用。
MSDN关于AsQueryable
的解释是:
如果源类型实现了
IQueryable<T>
,
AsQueryable<TElement>(IEnumerable<TElement>)
将直接返回它。否则,它返回一个
IQueryable<T>
,该IQueryable<T>
通过调用Enumerable
中的等效查询操作符方法来执行查询,而不是调用Queryable
中的方法。
所以这意味着在你的情况下(List<T>
没有实现IQueryable<T>
),你真的不需要使用AsQueryable
。
Do I really need to use AsQueryable() on a collection?
有时候我们在处理集合对象时,会遇到是否需要使用AsQueryable()方法的问题。在处理来自远程源(如数据库)的对象时,使用IQueryable是必需或者推荐的。但对于内存中的集合对象来说,使用IQueryable没有任何作用。
AsQueryable()方法用于构建表达式树。在下面的例子中,我们可以想象一种最适合使用AsQueryable()的场景。假设我们需要根据学生ID从数据库中获取一些信息。现在学生信息存储在内存集合中,我们需要根据学生ID来查询数据库。
var studentList = Students.Select(s => s.Id).AsQueryable().Select(i => remoteDBProvider.GetInfo(i));
对studentList的任何后续操作都将通过IQueryable接口(查询表达式)进行调用,并且只会从数据源中获取那些应该作为最终查询结果返回的记录(只要数据源支持QueryProvider,例如上面例子中的remoteDBProvider.GetInfo的返回值)。这是因为Queryable接受lambda表达式作为表达式,这允许查询提供程序检查表达式并将其转换为更高效的查询形式,例如SQL查询。任何投影或过滤都将在数据库中进行,而不是在应用程序中进行,以充分利用数据库的本地代码。但对于内存集合来说,这没有任何区别。
然而,即使对于内存集合来说,AsQueryable仍然有其用途,因为它的Select扩展方法接受一个Expression
,对于来自远程源的对象来说,使用IQueryable是必需或者推荐的。但对于内存中的集合对象来说,使用IQueryable并没有太大意义。然而,即使对于内存集合来说,AsQueryable仍然有其用途,因为它允许我们使用表达式树来分析或修改查询。