LINQ(Language Integrated Query),在 .Net Framework 3.5 之後發布的技術,讀作 “link”,不是 “另Q”。照中文翻譯就是語言整合查詢,大概就是這個意思,雖然背後有很多實作概念,但目前還沒有要提到。
使用關聯式資料庫儲存資料必然使用 SQL
語法查詢,LINQ 這項技術能夠讓你在程式語言中直接使用類似 SQL 語法來查詢、操作、聚合資料等。很古早時候要從一個陣列中找到符合條件的程式寫起來很辛苦,舉個例子,找到數值大於 5
的值有哪些:
1 | var data = new List<int>() {1,3,5,7,9}; |
當然,上述例子是比較誇張的,但事後回想,在 LINQ 問世前,或者工作經驗比較不足時,確實也都是類似的做法。
1 | var data = new List<int>() {1,3,5,7,9}; |
這樣是不是簡潔很多了?
不是!還可以再簡潔!
C# 這個語言進步速度飛快,扣除 語法糖(syntax sugar) 之外,很多技術都在持續演進中。上面這個語法我們稱為 查詢表示式(Query Expression)
,在多一點的操作後就會變得閱讀性不佳(當然,多看總會習慣的),不過實作上更多的是使用另一種表示方法,Lambda Expression
:
1 | var data = new List<int>() {1,3,5,7,9}; |
這兩者之間的差異就是哪個格式你看的習慣,或者團隊習慣使用哪一種,編譯後都是長得一樣的,所以也沒有存在效能上差異,除此之外 lamda 表示式還能夠延伸出更多使用的功能,在後面會演示一下。
以我個人的經驗來說,lamda 表示式是更方便排版與直觀上的閱讀。在設計上傾向讓這些 SQL 類型的過濾都放在資料庫做,一來這就是資料庫強項,二來減少資料傳輸 IO,把資料減少絕對是首選。
程式與資料庫效能這之間牽涉到很多東西,像是 entity framework, SQL/SP (甚至獨有的 T-SQL)等比較,就不在這邊討論,這很仰賴團隊資源、技術力、人員組成與協作,絕對無法找到最佳解,只有最適解
接下來的範例統一會使用 lambda expression….
延遲執行(載入)特性
LINQ 另一個特性就是帶來了延遲載入,也就是等到需要使用時,才會開始執行。這樣聽起來有點抽象,讓我們直接看例子:
我們同樣使用上面的範例,且這個範例就已經在使用延遲載入的特性囉!
宣告 greaterThan5Data
後,與 foreach
之間我們再加入幾個數值 13, 15
1 | var data = new List<int> {1,3,5,7,9}; |
從上面的例子可以看到在使用 LINQ 語法時,並沒有真正的去遍尋 data 整個 List,中間還插入了 2 個數值,直到 foreach 執行時,才去做判斷 item > 5
的確認。
小變化
可以思考一下這段程式:
1 | var data = new List<int> {1,3,5,7,9}; |
- 輸出為什麼是這樣?
- 什麼情境下會需要這樣使用?
延遲載入的優勢在於:只有需要使用到時,才會消耗 CPU 執行與 記憶體 的佔據
有使用 IDE 開發的,通常也會顯示 LINQ 的型別,通常是 IEnumerable<T>
如果不想要延遲載入怎麼辦
有些邏輯可能在 LINQ 語法不好寫,或是經驗不足,必須馬上取得結果的話,可以透過呼叫取得值
的方法,像是
- .First()
- .Average()
- .Max()
或是
- .ToArray()
- .ToList()
觀念上就是只要取得結果的,就會立刻執行。
LINQ 實際應用非常廣泛,甚至很多人會連為什麼這樣用,或者用到什麼技術都不見得達得上來,建議也可以深入了解一下。