假设我有一个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)
{
//...
}
}
根据参数的类型,可以使用不同的OrderBy
和ThenBy
方法。
Expression<Func<TSource, TKey>>
Func<TSource, TKey>
在DataContext.Log
中可以看到Queryable.OrderBy
将给定的表达式编译到通过数据库执行的SQL语句中,而当使用Enumerable.OrderBy
LINQ实际上对程序中的对象进行排序时内存,即对数据库的查询是在没有排序的情况下执行的......
我可能遇到的其他可能的特点是什么?
此问题出现在此之后:SO How to make expression treat value type as a reference type?
答案 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 execution。 IQueryable
实际上没有任何事情发生,直到某些东西迫使提供者对其进行评估。
另一方面,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()
调用强制提供程序在数据库中查询结果。在那之后,它全部在记忆中。