Queryable.OrderBy和Enumerable.OrderBy有什么区别?

时间:2013-11-25 01:38:35

标签: c# linq linq-to-sql linq-to-entities

假设我有一个LINQ to SQL(或EntityFramework)数据上下文(对象上下文)。我想从中查询一些数据并对结果集进行排序。查询看起来像:

using(var dc = new TestDataContext) // = new TestEntities)
{
    var query = dc.MyEntities.Where(e => /*my where clause*/)
                             .OrderBy(/*my sorting field*/)
                             .ThenBy(/*another sorting field*/);
    foreach(var entity in query)
    {
        //...
    }
}

根据参数的类型,可以使用不同的OrderByThenBy方法。

  1. Queryable.OrderBy Method Expression<Func<TSource, TKey>>
  2. Enumerable.OrderBy Method Func<TSource, TKey>
  3. DataContext.Log中可以看到Queryable.OrderBy将给定的表达式编译到通过数据库执行的SQL语句中,而当使用Enumerable.OrderBy LINQ实际上对程序中的对象进行排序时内存,即对数据库的查询是在没有排序的情况下执行的......

    我可能遇到的其他可能的特点是什么?

    此问题出现在此之后:SO How to make expression treat value type as a reference type?

2 个答案:

答案 0 :(得分:2)

  

DataContext.Log中可以看到Queryable.OrderBy编译了Enumerable.OrderBy   将表达式赋予在数据库上执行的SQL语句,   当使用Func<T> LINQ实际上进行排序时   在程序记忆中的对象上,

这是唯一的区别。并且因为编译器可以将您的lambda Expression<Func<T>>转换为Queryable.OrderBy,所以默认情况下将使用Expression<TDelegate>

  

当lambda表达式分配给类型为Enumerable.OrderBy的变量,字段或参数时,编译器会发出构建表达式树的指令。

     来自Expression<TDelegate> Class

如果您确实需要在AsEnumerable()来电之前执行LINQ to Objects OrderBy来电话{{1}}。

答案 1 :(得分:1)

这里的不同之处在于,诸如NHibernate和Entity Framework之类的持久性框架拥有自己的LINQ提供程序,这些提供程序遍历表达式树并构建SQL查询。这要感谢deferred executionIQueryable实际上没有任何事情发生,直到某些东西迫使提供者对其进行评估。

另一方面,LINQ可以在上述事件发生后进行内存查询。也许这会更有意义:

var result = db.Entities.Table
               .Where(x => x.Id == 1) // SQL WHERE clause
               .OrderBy(x => x.Id)    // SQL ORDER BY clause
               .ToList()              // Query the database and store result
               .Sum(x => x.SomethingElse) // Sum the field in memory
               .ToList();                 // convert back to a list.

正如您所看到的那样......提供商在中途通过生成的查询来访问数据库。 ToList()调用强制提供程序在数据库中查询结果。在那之后,它全部在记忆中。