Language Integrated Query (LINQ)

Language Integrated Query (LINQ) 是一組以直接將查詢功能整合至 C# 語言為基礎之技術的名稱。 傳統上,資料查詢是以簡單的字串表示,既不會在編譯時進行類型檢查,也不支援 IntelliSense。 此外,您還必須針對每種資料來源類型學習不同的查詢語言:SQL 資料庫、XML 文件、各種 Web 服務等等。 透過 LINQ,查詢會是第一級語言建構,和類別、方法及事件相同。

撰寫查詢時,LINQ 最明顯的「語言整合」部分就是查詢運算式。 查詢運算式是以宣告式「查詢語法」撰寫。 透過使用查詢語法,您就可以利用最少的程式碼,針對資料來源執行篩選、排序及分組作業。 您可以使用相同的查詢運算式模式,從任何類型的資料來源查詢和轉換資料。

下列範例示範完整的查詢作業。 完整的作業包括建立資料來源、定義查詢運算式,並在 foreach 陳述式中執行查詢。

// Specify the data source.
int[] scores = [97, 92, 81, 60];

// Define the query expression.
IEnumerable<int> scoreQuery =
    from score in scores
    where score > 80
    select score;

// Execute the query.
foreach (var i in scoreQuery)
{
    Console.Write(i + " ");
}

// Output: 97 92 81

您可能需要為上述範例新增 using 指示詞 (using System.Linq;) 才能進行編譯。 最新版本的 .NET 會使用隱含使用,將這個指示詞新增為全域使用。 舊版會要求您在來源中新增此指示詞。

查詢運算式概觀

  • 查詢運算式會從任何已啟用 LINQ 的資料來源查詢和轉換資料。 例如,單一查詢可以從 SQL 資料庫擷取資料,並產生 XML 串流作為輸出。
  • 查詢運算式使用許多熟悉的 C# 語言建構,因此使用者能夠輕鬆閱讀。
  • 查詢運算式中的變數全都是強型別。
  • 在您針對查詢變數進行逐一查看之前 (例如,在 foreach 陳述式中),查詢將不會執行。
  • 在編譯期間,查詢運算式會根據 C# 規格中定義的規則,轉換成「標準查詢運算子」方法呼叫。 所有可使用查詢語法表示的查詢,也都可以利用方法語法來表示。 不過,在大多數案例中,查詢語法較容易閱讀且更簡潔。 在其他案例中,方法語法更容易閱讀。 這兩個形式之間並沒有語意或效能上的差異。 如需詳細資訊,請參閱 C# 語言規格標準查詢運算子概觀
  • 某些查詢作業 (例如 CountMax) 沒有同等的查詢運算式子句,因此必須以方法呼叫來表示。 方法語法能以數種方式來與查詢語法結合。
  • 根據查詢所套用的型別,可將查詢運算式編譯為運算式樹狀結構或委派。 IEnumerable<T> 查詢會編譯成委派。 IQueryableIQueryable<T> 查詢會編譯成運算式樹狀架構。 如需詳細資訊,請參閱運算式樹狀結構

如何啟用資料來源的 LINQ 查詢功能

記憶體中的資料

您可以使用兩種方式來啟用記憶體內部資料的 LINQ 查詢。 如果資料屬於實作 IEnumerable<T> 的型別,您可以使用 LINQ to Objects 來查詢資料。 如果藉由實作 IEnumerable<T> 介面來啟用列舉不是合理的作法,您可以在該型別中定義 LINQ 標準查詢運算子方法,或將其定義為該型別的擴充方法。 標準查詢運算子的自訂實作 (Implementation) 應該會使用延後執行 (Deferred Execution) 來傳回結果。

遠端資料

若要啟用遠端資料來源的 LINQ 查詢,最佳選項為實作 IQueryable<T> 介面。

IQueryable LINQ 提供者

實作 IQueryable<T> 的 LINQ 提供者在複雜度上可能會有很大的差異。

較不複雜的 IQueryable 提供者可能會從 Web 服務存取單一方法。 這種類型的提供者非常特別,因為它預期本身所處理的查詢中應該有特定的資訊。 這種提供者具有封閉類型系統,可能會公開單一結果類型。 多數的查詢執行工作都是在本機進行,例如利用標準查詢運算子的 Enumerable 實作。 複雜度較低的提供者可能只會在代表查詢的運算式樹狀架構中檢查一個方法呼叫運算式,並讓查詢的其餘邏輯在其他地方處理。

複雜度中等的 IQueryable 提供者可能以具有部分表示查詢語言的資料來源為目標。 如果以 Web 服務為目標,其可能會存取一個以上的 Web 服務方法,並根據查詢所搜尋的資訊選取要呼叫的方法。 中等複雜度的提供者擁有的類型系統雖然比簡單提供者更為多樣化,但仍然為固定類型系統。 例如,提供者可能會公開具有可周遊的一對多關聯性 (One-To-Many Relationship),但卻不會提供使用者定義型別的對應技術。

複雜的 IQueryable 提供者 (例如 Entity Framework Core 提供者) 可能會將完整的 LINQ 查詢轉譯為表達式查詢語言,例如 SQL。 複雜的提供者更為廣泛,因為其可以在查詢中處理更多種類的問題。 它也具有開放類型系統,因此必須包含廣泛的基礎結構,以對應使用者定義的類型。 開發複雜的提供者需要花費相當大量的心力。