LINQ 方法和 IEnumerableT 与 IQueryableT
关于 IEnumerable<T>
的 LINQ 扩展方法采用实际方法 1 ,是否匿名方法:
//C#
Func<int,bool> fn = x => x > 3;
var list = new List<int>() {1,2,3,4,5,6};
var query = list.Where(fn);
'VB.NET
Dim fn = Function(x As Integer) x > 3
Dim list = New List From {1,2,3,4,5,6};
Dim query = list.Where(fn);
或命名方法(明确定义为类的一部分的方法):
//C#
class Program {
bool LessThan4(int x) {
return x < 4;
}
void Main() {
var list = new List<int>() {1,2,3,4,5,6};
var query = list.Where(LessThan4);
}
}
'VB.NET
Class Program
Function LessThan4(x As Integer) As Boolean
Return x < 4
End Function
Sub Main
Dim list = New List From {1,2,3,4,5,6};
Dim query = list.Where(AddressOf LessThan4)
End Sub
End Class
从理论上讲,可以解析方法的 IL ,弄清楚方法尝试做什么,并将该方法的逻辑应用于任何底层数据源,而不仅仅是内存中的对象。但解析 IL 不适合胆小的人。
幸运的是,.NET 提供了 IQueryable<T>
接口,以及 System.Linq.Queryable
的扩展方法。这些扩展方法采用表达式树 - 表示代码的数据结构 - 而不是实际方法,然后 LINQ 提供程序可以解析 2 并转换为更合适的形式以查询底层数据源。例如:
//C#
IQueryable<Person> qry = PersonsSet();
// Since we're using a variable of type Expression<Func<Person,bool>>, the compiler
// generates an expression tree representing this code
Expression<Func<Person,bool>> expr = x => x.LastName.StartsWith("A");
// The same thing happens when we write the lambda expression directly in the call to
// Queryable.Where
qry = qry.Where(expr);
'VB.NET
Dim qry As IQueryable(Of Person) = PersonSet()
' Since we're using a variable of type Expression(Of Func(Of Person,Boolean)), the compiler
' generates an expression tree representing this code
Dim expr As Expression(Of Func(Of Person, Boolean)) = Function(x) x.LastName.StartsWith("A")
' The same thing happens when we write the lambda expression directly in the call to
' Queryable.Where
qry = qry.Where(expr)
如果(例如)此查询针对 SQL 数据库,则提供程序可以将此表达式转换为以下 SQL 语句:
SELECT *
FROM Persons
WHERE LastName LIKE N'A%'
并针对数据源执行它。
另一方面,如果查询针对 REST API,则提供程序可以将同一表达式转换为 API 调用:
http://www.example.com/person?filtervalue=A&filtertype=startswith&fieldname=lastname
基于表达式定制数据请求有两个主要好处(而不是将整个集合加载到内存中并在本地查询):
- 底层数据源通常可以更有效地查询。例如,
LastName
上可能有一个索引。将对象加载到本地内存并查询内存会失去效率。 - 数据可以在传输之前进行整形和缩小。在这种情况下,数据库/ Web 服务只需要返回匹配的数据,而不是从数据源中获得的整个人员集。
注释
1.从技术上讲,它们实际上并不采用方法,而是委托指向方法的实例 。但是,这种区别在这里无关紧要。
2.这就是 “ LINQ to Entities 无法识别方法’System.String ToString()
‘方法等 错误的原因*,并且此方法无法转换为商店表达式。* ” LINQ 提供程序(在本例中为 Entity Framework 提供程序)不知道如何解析和转换对 ToString
的调用到等效的 SQL。 **