【问题标题】:Do i really need use AsQueryable() on collection?我真的需要在收集时使用 AsQueryable() 吗?
【发布时间】:2012-05-17 15:52:27
【问题描述】:

示例代码:

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;

这也有效并产生相同的结果,那么有什么区别?

【问题讨论】:

标签: c# .net linq list asqueryable


【解决方案1】:

对于来自远程源(如来自数据库)的对象,需要/推荐使用 IQueryable。

在内存集合中它是没有用的。

AsQueryable在构建表达式树时使用。

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

现在学生正在记忆收集中。您需要根据学生 ID 触发数据库查询。

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

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

【讨论】:

  • @BorisB。那明显是错的。 Enumerable.Select 也使用延迟执行。不同之处在于 Queryable 接受 lambda 作为表达式。这允许查询提供者检查表达式并将其转换为(可能)更有效的东西,例如SQL 查询。任何投影或过滤都将在数据库中而不是在应用程序中进行,从而利用数据库的本机代码。但对于内存中的集合,它没有任何区别。
  • @NielsvanderRest:你是​​对的,评论被删除,因为它具有误导性(或者根本不真实)。尽管如此,AsQueryable 仍然可以用于内存收集,因为它的Select 扩展方法接受Expression&lt;Func&gt;,这使您能够分析或修改它。我能想到的一个场景是使用封装在IQueryable 中的内存中集合作为不感知持久性的层将查询作为 AST 发送到感知持久性的层的一种方式。
【解决方案2】:

对于您的List&lt;Student&gt;,它没有任何区别,因为返回的IQueryable&lt;T&gt; 将使用与您根本没有使用AsQueryable() 相同的方法进行查询。

某些方法需要IQueryable&lt;T&gt; 参数。我认为AsQueryable() 扩展方法最适用于那些场景,当你需要传递一个IQueryable&lt;T&gt; 但只有一个IEnumerable&lt;T&gt;

MSDN 说AsQueryable

如果源类型实现IQueryable&lt;T&gt;AsQueryable&lt;TElement&gt;(IEnumerable&lt;TElement&gt;) 直接返回。 否则,它会返回一个IQueryable&lt;T&gt;,它通过以下方式执行查询 在Enumerable 中调用等效的查询运算符方法而不是 Queryable中的那些。

这意味着在你的情况下(List&lt;T&gt; 没有实现IQueryable&lt;T&gt;),你真的不需要AsQueryable

【讨论】:

    【解决方案3】:

    它必须执行表达式树的构建方式。看看这个:

    AsQueryable 是一种允许将查询转换为 IQueryable 的实例。当您使用 AsQueryable 运算符时 现有查询并应用进一步的转换,例如应用 过滤或指定排序顺序,这些 lambda 语句是 转换为表达式树。取决于您的提供商 使用,表达式树将被转换为特定领域 语法,然后执行。对于 Linq to SQL 提供程序, 表达式树将被转换为 SQL 并在 SQL 服务器上执行。 但是,如果您在不支持的查询上使用 AsQueryable 运算符 实现 IQueryable 并且只实现 IEnumerable,而不是任何 您对查询应用的转换将自动下降 回到 IEnumerable 规范。这意味着通过标记 使用 AsQueryable 进行查询,您可以获得 Linq to SQL 和 Linq 的好处 对象实现。如果您现有的查询恰好实现 IQueryable,查询由 Linq to SQL 提供程序转换为 SQL, 否则查询将以 IL 代码的形式在内存中执行。

    参考here

    【讨论】:

      猜你喜欢
      • 2018-06-11
      • 1970-01-01
      • 2012-03-13
      • 2020-01-29
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多