2008年4月23日 星期三

LINQ初探

LINQ(Language-Integrated Query)是VS2008和Framework 3.5中的突破性創舉,是一系列擴充方法的組合,它的核心是System.Collection.Generic命名空間中,名稱為IEnumerable(T)這個型別,其中所定義的方法成員,成了LINQ資料查詢技術的基礎,可適用於各種型態的資料來源的存取操作,包括SQL Server資料庫、XML文件、ADO.NET Dataset、文字檔、陣列、以及任何支援IEnumerable或泛型IEnumerable(T)介面的物件組成的集合。

當有一陣列內容為:

Dim sFruit As String() = {"葡萄", "香蕉", "哈蜜瓜", "香瓜", "棷子", "蘋果", "木瓜"}
若要找出以"瓜"為結尾的陣列元素,過去的寫法通常是用迴圈來取得(為搭配後面的程式,此處用兩組迴圈完成,而不是直接以一組迴圈取得。第一組迴圈為主要取得符合條件的元素陣列,在後續程式中,將會被LINQ寫法取代):
Dim s As String = ""
Dim myEnumFruit As New ArrayList
For Each myFruit As String In sFruit
If myFruit.EndsWith("瓜") Then
myEnumFruit.Add(myFruit)
End If
Next
Dim s As String = ""
For Each myFruit As String In myEnumFruit
s &= myFruit & vbCrLf
Next
MsgBox(s)
若改為應用IEnumerable時,則可寫成:
Dim myEnumFruit As IEnumerable(Of String) = sFruit.Where(Function(fruit) fruit.EndsWith("瓜"))
Dim s As String = ""
For Each myFruit As String In myEnumFruit
s &= myFruit & vbCrLf
Next
MsgBox(s)
上面程式碼,當執行更為複雜的查詢運算時,程式會變得更加複雜而不易理解。
而若直接以LINQ寫法來處理時,將上述第一行程式碼改為:
Dim myEnumFruit = From fruit In sFruit Where fruit.EndsWith("瓜") Select fruit
因為採用與SQL類似的From、Where、Select...等,讓程式設計時,針對各種不同的資料來源,可以運用統一的資料存取模型去操作,不必再去記一堆針對不同資料來源的處理方式,也不必再去理會那複雜而難以理解的IEnumerable寫法,而只需要將心力花費在程式的實際應用面部份即可。

然而,要注意的是,上頭LINQ寫法中的myEnumFruit這個查詢變數本身並不會採取任何動作,也不會傳回任何資料,它只會儲存查詢定義,真正負責查詢的是後面的For Each迴圈。因此,上述寫法稱為『延後執行』。

而若是要改寫為『立即執行』方式,則可如下:
Dim myEnumFruit As List(Of String) = (From fruit In sFruit Where fruit.EndsWith("瓜") Select fruit).ToList

關於『延後執行』與『立即執行』的差異,由下列兩組程式便可看出:
一、延後執行

Dim sFruit As String() = {"葡萄", "香蕉", "哈蜜瓜", "香瓜", "棷子", "蘋果", "木瓜"}
Dim myEnumFruit = From fruit In sFruit Where fruit.EndsWith("瓜") Select fruit
sFruit(1) = "胡瓜" '因是延後執行, 這項內容改變, 將導致後續結果也跟著改變, 會在結果中出現"胡瓜"這一項
Dim s As String = ""
For i As Integer = 0 To myEnumFruit.Count - 1
s &= myEnumFruit(i) & vbCrLf
Next
MsgBox(s)
二、立即執行

Dim sFruit As String() = {"葡萄", "香蕉", "哈蜜瓜", "香瓜", "棷子", "蘋果", "木瓜"}
Dim myEnumFruit As List(Of String) = _
(From fruit In sFruit Where fruit.EndsWith("瓜") Select fruit).ToList
sFruit(1) = "胡瓜" '因是立即執行, 這項內容改變, 並沒有影響後續結果, 因此"胡瓜"並沒有在結果中出現
Dim s As String = ""
For i As Integer = 0 To myEnumFruit.Count - 1
s &= myEnumFruit(i) & vbCrLf
Next
MsgBox(s)


運用上述LINQ技術,應引用下面兩個命名空間
Imports System.Collections.Generic
Imports System.Linq
不過,似乎VB2008已貼心的自動引入,即使我們在程式中沒有打入這兩行引入命名空間程式碼,亦可正常執行。

LINQ技術包括三個部份,LINQ to ObjectsLINQ to XMLLINQ to ADO.NET(含LINQ to SQLLINQ to Dataset)。

0 意見: