認識基礎 LINQ

前言

LINQ,全名 Language Integrated Query,表示和語言整合,具有查詢能力的技術。

LINQ 的特點

  • 整合了 C#、VB 程式語言。
  • 使用相同的語法來對不同資料類型 (例如:物件、關聯式資料庫以及 DataSet、XML) 進行查詢。
  • 技術類型分成:
    • LINQ to Object
    • LINQ to ADO.NET (LINQ to SQL 和 LINQ to Dataset)
    • LINQ to XML
    • … 等
  • 有實作 IEnumerableIEnumerable<T>IQueryableIQueryable<T> 的 Class,才能被 LINQ 查詢。
    • 泛型集合 (Generic collections) e.g. List<T>, Dictionary<TKey,TValue> 實作 IEnumerableIEnumerable<T>
    • Entity Framework api 實作 IEnumerableIQueryable<T>

LINQ to Object

有實作 IEnumerableIEnumerable<T> 的集合物件,才能被 LINQ 查詢。

記得引入 using System.Linq; 命名空間。

1
2
3
4
5
6
7
using System.Linq;

int[] grades = new int[] { 60, 35, 89, 78, 25, 100, 87 };

var higherThan70Grades = from g in grades // g 是隨意命名的
where g > 70
select g;

名詞解釋

在談 LINQ to SQL 前,先來了解兩個詞:模型抽象

Model 模型

什麼是程式語言中所謂的 Model?Model 就是對實際的問題、客觀的事物或客觀的規律,進行抽象化後的一種形式化的表達方式。

特徵是:

  • 抽象簡化
  • 描述或預測

抽象化

抽象的意義是可以忽略不是求解過程中必需的解。例如要用電腦程式去類比「人」,在描述了人的動作(飲食、思考、移動等)符合設計要求後(如可完整表達「人」在坐下時候的動作),其他「人」的細節(軀幹、器官、細胞活動乃至人際關係)都可以忽略,以集中設計需要的功能,並減低程式的複雜度。

參考資料:
抽象化 (計算機科學)

LINQ to SQL

LINQ to SQL 是一種擁有物件關聯對映 (Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping) 的程式設計技術。Object 就是物件導向程式設計 Object-oriented programming 的「物件」。Relational 就是關聯式資料庫 Relational Database 的「關聯」。故而,是一種能將物件和資料庫相對映的技術

能夠形成「物件模型」和「資料庫」相互對映。透過 LINQ to SQL 的物件模型,LINQ Query 查詢語句會轉換成 SQL Query 查詢語句,再與 SQL Server 溝通。SQL Server 回傳的資料也會透過物件模型,轉換成程式理解的物件。

1
2
3
4
5
using System.Linq;

var studentsWithA = from s in students
where s.grage = "A"
select new { s.id, s.firstName, s.lastName, s.grade };

也可以對有實作 IQueryable<T> 的物件做查詢。

Query Expression Syntax 查詢語法

from 語句開頭,以 selectgroup ... by 語句結尾的查詢語法 (跟 SQL 查詢語法很像),就稱為 Query Expression Syntax 查詢語法,或是 Query Syntax。

以寫在 C# 中的 LINQ to Object 為例:

1
2
3
4
5
6
7
8
9
10
11
using System.Linq;

List<Student> students = new List<Student>() {
new Student() { id = 1, firstName = "Lucky", lastName = "Lee", grade = "A" },
new Student() { id = 2, firstName = "Marry", lastName = "Wang", grade = "B" },
new Student() { id = 3, firstName = "Cola", lastName = "Lin", grade = "A" }
};

var studentsWithA = from s in students
where s.grage = "A"
select s;

Method Extension Syntax 方法語法

Method Extension Syntax 方法語法又稱為 Method Syntax 或 Fluent 流利語法。就是直接使用 EnumerableQueryable Class 跟查詢相關的那些 Extension Methods,例如:Where()、OrderBy()、Sum()。

如果回傳型別是 IEnumerable<TSource>,就可以用點運算子將方法鏈結在一起。

其中有些方法的參數,是要接受 predicate delegate 委派方法,像是 Where() 如下:

1
2
3
4
using System.Collections.Generic;

// 回傳型別 // 方法名
public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);

而委派方法可以用 Lambda 表達式 (Lambda Expression) 取代。Lambda 表達式是匿名函式的縮寫,不會的人可以參考這篇

因此上面的例子可以寫成:

1
2
3
4
5
using System.Linq;

var studentsWithA = students
.Where(s => s.grage == "A")
.ToList<Student>();

會 javascript 的人只要把 Where() 想像成是 Array.filter() 就可以了。像是:

1
2
3
4
5
6
7
8
const student1 = {
id: 1, firstName: "Lucky", lastName: "Lee", grade: "A"
};
const student2 = {
id: 2, firstName: "Marry", lastName: "Wang", grade: "B"
};
const students = [student1, student2];
let _students = students.filter(s => s.grage === "A");

Query Operators 查詢運算子

我對 javascript 的陣列語法比較熟悉,想要以此將兩方做個類比,方便記憶和理解:

LINQ JavaScript
Where() filter()
OrderBy() sort()
Select() map()
All() every()
Any() some()
Contains() includes()
Aggregate() reduce()
First() find()
Last() findLast()
Concat() concat()

更詳細的內容請參考:
LINQ - Query Operators
Standard Query Operators