我真的需要在集合上使用AsQueryable()吗?

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);
}

但是如果我将查询更改为

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

这也可以使用并产生相同的结果,那么有什么区别呢?


关于AsEnumerable的类似问题。 - nawfal
3个回答

10

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

对于内存集合,它没有作用。

AsQueryable用于构建表达式树。

我可以想到最适合的情况。在您的示例中,假设您需要根据学生ID从数据库获取一些信息。

现在学生在内存集合中。您需要基于学生ID触发数据库查询。

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

任何对studentList的进一步操作都将通过IQueryAble接口(查询表达式)调用,并且仅从数据源获取那些应作为最终查询结果返回的记录(只要数据源,即示例中的remoteDBProvider.GetInfo的返回值,支持QueryProvider)。

6
@BorisB。那不是真的。Enumerable.Select 也使用延迟执行。区别在于Queryable接受lambda表达式作为参数。这允许查询提供程序检查表达式并将其转换为(可能)更有效的内容,例如SQL查询。任何投影或过滤都将在数据库中而不是应用程序中进行,利用数据库的本地代码。但对于内存集合,它没有任何区别。 - Niels van der Rest
@NielsvanderRest:你说得对,评论已删除,因为它具有误导性(或者根本不正确)。尽管如此,即使对于内存集合,AsQueryable 仍然有其用途,因为它的 Select 扩展方法接受一个 Expression<Func>,这使您能够分析或修改它。我能想到的一个场景是,使用包装在 IQueryable 中的内存集合作为一种方式,让无持久性意识的层将查询作为 AST 发送到有持久性意识的层。 - Boris B.

3
在您的List<Student>情况下,使用AsQueryable()与不使用它时查询返回的IQueryable<T>方法是相同的,没有任何区别。
一些方法需要一个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

2
这与表达式树的构建方式有关。看看这个:
AsQueryable是一种方法,允许将查询转换为IQueryable的实例。当您在现有查询上使用AsQueryable运算符并应用进一步的转换,如应用过滤器或指定排序顺序时,这些lambda语句将被转换为表达式树。根据您使用的提供程序,表达式树将被转换为特定于域的语法,然后执行。在Linq to SQL提供程序的情况下,表达式树将被转换为SQL并在SQL服务器上执行。但是,如果您在仅实现IEnumerable而不实现IQueryable的查询上使用AsQueryable运算符,则应用于查询的任何转换都会自动回退到IEnumerable规范。这意味着通过使用AsQueryable标记查询,您可以获得Linq to SQL和Linq to对象实现的好处。如果您现有的查询恰好实现了IQueryable,则由Linq to SQL提供程序将查询转换为SQL,否则查询将以IL代码的形式在内存中执行。
参考 这里

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接