2008年6月18日 星期三

LINQ其實很簡單

會寫這一篇是有原因的,不只一次有人問我,要不要學LINQ呢?
LINQ看起來很難耶...為何要放棄以前的SQL來學LINQ呢?到底LINQ的意義是什麼?

反正就是有一缸子的問題,說真的,由於最近也沒時間寫本LINQ的書,但是工作累了順手寫寫BLOG還可以,所已針對LINQ這個主題,和大家有一些分享。

其實對於VB開發人員來說,掌握LINQ說真的比C#來的簡單很多,主要的原因就是VB當中有非常多"自動"的隱含型別轉換,是不需要寫程式碼的,也因此操作起來比起C#真的容易不少。

要掌握LINQ的精神,得要知道LINQ出現的目的,其實很簡單,只有一句話,就是希望 "能夠達成以單一的一種語法來查詢多種不同的對象" 的目的。這其來有自,過去我們要查詢資料庫要用SQL、要查詢XML要用XMLDOM物件、要查詢AD又要用另一種不同的查詢方式,總之,查詢這個動作一天到晚出現在電腦程式碼當中,但是開發人員卻要學習多種不同的方式,很困擾,所以LINQ就出現了。

所謂的LINQ,是 .NET Language Integrated Query,也就是在.NET的開發語言當中,直接把查詢的技術給 "整" 進去,目的就是要加快搜尋(速度)與降低開發成本。

所以從.NET 3.5開始, LINQ變成.NET標準語法的一部分,OK,就是這樣,所以我們來看看 LINQ怎麼查詢,首先,為了展示LINQ,我定義了底下這樣的結構:

Structure BMI
  Dim name As String
  Dim height As Integer
  Dim weight As Integer
  Dim BmiValue As Single
End Structure

你用類別也可以,總之上面的結構用來表達一個人的身高,體重,名稱和BMI值。

接著,我撰寫底下程式碼:

'定義陣列
Dim matrix(5) As BMI
'填入測試資料
matrix(0).name = "王小寶"
matrix(0).height = 170
matrix(0).weight = 65
matrix(1).name = "韋大寶"
matrix(1).height = 176
matrix(1).weight = 95
matrix(2).name = "章新寶"
matrix(2).height = 150
matrix(2).weight = 55
matrix(3).name = "沈中寶"
matrix(3).height = 192
matrix(3).weight = 75
matrix(4).name = "蕭敦寶"
matrix(4).height = 150
matrix(4).weight = 65
matrix(5).name = "林寶寶"
matrix(5).height = 177
matrix(5).weight = 75

上面這段程式碼就只是很簡單的把資料填入,請注意我們只填入身高體重和姓名,接著,再利用底下的程式碼算出BMI:

'計算BMI
For i = 0 To 5
  matrix(i).BmiValue = matrix(i).weight / (matrix(i).height / 100) ^ 2
Next

OK,到這邊先告一個段落,以上都沒有LINQ出現,動作也很簡單,接下來換LINQ出場,在出場前先問讀者一個問題,如果要找出BMI值>25的資料,你會怎麼寫程式?

...

沒錯,用for each指令,在沒有LINQ功能的時代,我們只能用陣列巡覽的方式查找每一個元素,找出符合的資料,但是有底下幾個問題:
1.為了找出特定的資料而跑整個陣列,看起來挺蠢的。(不過說真的,如果資料沒有排序,也就只能那麼蠢)
2.可能有一些初學的菜鳥程式設計師,寫出效率很差的查找程式。(例如不小心在for each當中做了一些不必要的動作)

OK,過去我們對於物件(或是物件陣列)的操作,也就只能使用迴圈的方式,但是LINQ提出了一種新的可能,就是透過類似SQL的查找語法,讓開發人員可以用簡單的程式碼,就可以針對物件進行複雜的查詢。(更重要的是,未來這種簡單的查找語法變成主流之後,可以用以查詢"各種不同的對象",而不只有查找"物件")

言歸正傳,若要查找出BMI值>25的資料,你可以透過底下的LINQ程式:

'查詢BMI值大於25的人
Dim result = From c In matrix Where c.BmiValue > 25

結束,就是這樣,而 result 就是找出的結果物件,你可以透過 result 來取得每一個符合條件的資料。簡單的說,上面這段程式碼的意思是,從matrix物件集合當中,找出一些資料,這些資料的BmiValue屬性大於25。其中的 c 只是撰寫程式碼方便,c代表該物件元素,你也可以用別的字眼..

而找出的資料result也是一個集合,你可以透過底下的程式碼來列出每一個BMI值符合條件者的名字:

'顯示名稱
For Each item In result
  MsgBox(item.name)
Next

很簡單不是嗎? result 當中的每一個 item ,其型別就是 BMI,因為Result物件是LINQ語法跑出的結果,所以只有包含符合 BmiValue > 25 這個條件的人...

上面這段程式碼,還可以這樣寫...

'顯示名稱
For Each item In (From c In result Select c.name)
  MsgBox(item)
Next

效果完全一樣唷,但是,(From c In result Select c.name) 會產生一個物件,該物件只有符合條件者的名稱(相當於一維陣列),而item的型別當然就是string。

透過上面這樣的指令,查找動作變得相當簡單,還不僅如此,關鍵在於底下這樣的語法:

'查詢BMI值大於25的人
Dim result = From c In matrix Where c.BmiValue > 25

具有相當多不同的變化方式,可以組合出各種不同的形式,發揮出強大的查找力量,再加上學一次,就可以用在各種不同的地方(這邊我們只用來查找物件,其實也可以查找XML和Database),使得LINQ的用途更加的廣泛,這就是LINQ的價值與意義。

以後,再跟大家分享一些關於LINQ的其他部分,希望對大家有幫助,VB developer其實是幸福的,LINQ其實是很簡單的...

7 則留言:

LINQ初學者 提到...

謝謝老師,茅塞頓開啦~

匿名 提到...

老師會再繼續介紹一些 LINQ 的應用嗎?

匿名 提到...

LINQ畢竟只在.NET 3.5支援,老師建議我們在程式碼當中,開始使用LINQ嗎?還是過一兩年等到.NET 4.0再說?

David Dong 董大偉 的介紹 提到...

會的LINQ的部分應該會整理幾篇文章出來,何時開始用?現在囉~

花花 提到...

真的很謝謝您的解說><
翻書一直不懂LINQ的意思到底是甚麼,可是經過您一說,整個都明朗了!!真的很謝謝!!

Unknown 提到...

請教前輩
直接練習那個範例的時候,會出現下列錯誤訊息
-->型別'1-維陣列屬於Default6.Weight'的運算式無法查詢,請確定您有沒有遺漏組件參考及(或)LINQ提供者的命名空間匯入。

(卡在Dim result = From c In matrix Where c.BmiValue > 25這一行)

且 For Each item In result
MsgBox(item.name)
Next
它會說item還沒有宣告,
煩請前輩指點
謝謝

匿名 提到...

謝謝分享!! 終於了解LinQ 的用法