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。 **