LINQ 快速指南



LINQ - 概述

全世界的開發者都曾經在資料查詢方面遇到問題,因為缺乏明確的路徑,並且需要掌握多種技術,例如 SQL、Web 服務、XQuery 等。

LINQ(語言整合查詢)由 Anders Hejlsberg 設計,在 Visual Studio 2008 中引入,允許編寫查詢而無需瞭解 SQL、XML 等查詢語言。LINQ 查詢可以編寫用於各種資料型別。

LINQ 查詢示例

C#

using System;
using System.Linq;

class Program {
   static void Main() {
   
      string[] words = {"hello", "wonderful", "LINQ", "beautiful", "world"};
		
      //Get only short words
      var shortWords = from word in words where word.Length <= 5 select word;
	    
      //Print each word out
      foreach (var word in shortWords) {
         Console.WriteLine(word);
      }	 
		
      Console.ReadLine();
   }
}

VB

Module Module1
   Sub Main()
      Dim words As String() = {"hello", "wonderful", "LINQ", "beautiful", "world"}
     
      ' Get only short words
      Dim shortWords = From word In words _ Where word.Length <= 5 _ Select word
     
      ' Print each word out.
	  
      For Each word In shortWords
         Console.WriteLine(word)
      Next
	  
      Console.ReadLine()
   End Sub
End Module	

當編譯並執行上述 C# 或 VB 程式碼時,將產生以下結果:

hello 
LINQ 
world

LINQ 的語法

LINQ 有兩種語法。它們如下所示。

Lambda(方法)語法

var longWords = words.Where( w ⇒ w.length > 10);
Dim longWords = words.Where(Function(w) w.length > 10)

查詢(理解)語法

var longwords = from w in words where w.length > 10;
Dim longwords = from w in words where w.length > 10

LINQ 的型別

LINQ 的型別簡述如下。

  • LINQ to Objects
  • LINQ to XML(XLINQ)
  • LINQ to DataSet
  • LINQ to SQL (DLINQ)
  • LINQ to Entities

除了上述內容外,還有一種名為 PLINQ 的 LINQ 型別,它是 Microsoft 的並行 LINQ。

.NET 中的 LINQ 架構

LINQ 在 .NET 中採用三層架構,最上層由語言擴充套件組成,底層由資料來源組成,這些資料來源通常是實現 IEnumerable <T> 或 IQueryable <T> 通用介面的物件。架構如下所示。

LINQ Architecture

查詢表示式

查詢表示式只不過是以類似於 SQL 的形式表達的 LINQ 查詢,使用 Select、Where 和 OrderBy 等查詢運算子。查詢表示式通常以關鍵字“From”開頭。

要訪問標準 LINQ 查詢運算子,預設情況下應匯入名稱空間 System.Query。這些表示式寫在宣告性查詢語法中,這是 C# 3.0。

以下是一個示例,演示完整的查詢操作,其中包括資料來源建立、查詢表示式定義和查詢執行。

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Operators {
   class LINQQueryExpressions {
      static void Main() {
      
         // Specify the data source.
         int[] scores = new int[] { 97, 92, 81, 60 };

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

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

當編譯並執行上述程式碼時,將產生以下結果:

97 92 81

擴充套件方法

擴充套件方法是在 .NET 3.5 中引入的,僅在靜態類中宣告,允許將自定義方法新增到物件以執行一些精確的查詢操作,從而擴充套件類而無需成為該類的實際成員。這些也可以過載。

簡而言之,擴充套件方法用於將查詢表示式轉換為傳統的元方法呼叫(面向物件)。

LINQ 與儲存過程的區別

LINQ 與儲存過程之間存在許多差異。這些差異如下所述。

  • 儲存過程比 LINQ 查詢快得多,因為它們遵循預期的執行計劃。

  • 與儲存過程相比,執行 LINQ 查詢更容易避免執行時錯誤,因為前者具有 Visual Studio 的 IntelliSense 支援以及編譯時的完整型別檢查。

  • LINQ 允許使用 .NET 偵錯程式進行除錯,而儲存過程則不行。

  • LINQ 支援多個數據庫,而儲存過程則需要為不同型別的資料庫重寫程式碼。

  • 與部署一組儲存過程相比,部署基於 LINQ 的解決方案更加容易和簡單。

LINQ 的需求

在 LINQ 之前,需要學習 C#、SQL 和將兩者結合在一起形成完整應用程式的各種 API。由於這些資料來源和程式語言存在阻抗不匹配;因此,需要簡短的編碼。

以下是一個示例,說明在 LINQ 出現之前,開發人員在查詢資料時使用了多少種不同的技術。

SqlConnection sqlConnection = new SqlConnection(connectString);
SqlConnection.Open();

System.Data.SqlClient.SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Connection = sqlConnection;

sqlCommand.CommandText = "Select * from Customer";
return sqlCommand.ExecuteReader (CommandBehavior.CloseConnection)  

有趣的是,在特色程式碼行中,查詢僅由最後兩行定義。使用 LINQ,可以在更短的時間內以可讀的彩色編碼形式編寫相同的資料查詢,如下所示。

Northwind db = new Northwind(@"C:\Data\Northwnd.mdf");
var query = from c in db.Customers select c;

LINQ 的優勢

LINQ 提供了許多優勢,其中最重要的是其強大的表達能力,使開發人員能夠宣告性地表達。LINQ 的其他一些優勢如下所示。

  • LINQ 提供語法突出顯示,有助於在設計時查詢錯誤。

  • LINQ 提供 IntelliSense,這意味著可以輕鬆編寫更準確的查詢。

  • 在 LINQ 中編寫程式碼的速度非常快,因此開發時間也大大減少。

  • 由於 LINQ 整合到 C# 語言中,因此可以輕鬆進行除錯。

  • 由於 LINQ 的分層特性,檢視兩個表之間的關係很容易,這使得能夠在更短的時間內組合連線多個表的查詢。

  • LINQ 允許在查詢許多不同的資料來源時使用單個 LINQ 語法,這主要是因為其統一的基礎。

  • LINQ 是可擴充套件的,這意味著可以使用 LINQ 知識來查詢新的資料來源型別。

  • LINQ 提供在單個查詢中連線多個數據源以及將複雜問題分解為易於除錯的一組簡短查詢的功能。

  • LINQ 提供了一種將一種資料型別轉換為另一種資料型別(例如將 SQL 資料轉換為 XML 資料)的簡單轉換方法。

LINQ - 環境設定

在開始使用 LINQ 程式之前,最好先了解設定 LINQ 環境的細微之處。LINQ 需要 .NET Framework,這是一個革命性的平臺,可以擁有各種各樣的應用程式。可以使用 C# 或 Visual Basic 方便地編寫 LINQ 查詢。

Microsoft 透過 Visual Studio 提供這兩種語言(即 C# 和 Visual Basic)的工具。我們的示例都在 Visual Studio 2010 中編譯和編寫。但是,Visual Basic 2013 版本也可供使用。它是最新版本,與 Visual Studio 2012 具有許多相似之處。

在 Windows 7 上安裝 Visual Studio 2010

Visual Studio 可以從安裝介質(如 DVD)安裝。成功在系統上安裝 Visual Basic 2010 需要管理員憑據。在安裝之前,務必斷開所有可移動 USB 裝置與系統的連線,否則安裝可能會失敗。安裝所需的一些硬體要求如下。

硬體要求

  • 1.6 GHz 或更高
  • 1 GB RAM
  • 3 GB(可用硬碟空間)
  • 5400 RPM 硬碟驅動器
  • 相容 DirectX 9 的顯示卡
  • DVD-ROM 驅動器

安裝步驟

步驟 1 - 首先插入包含 Visual Studio 2010 軟體包的 DVD,然後單擊螢幕上彈出框中顯示的“安裝或從您的媒體執行程式”

步驟 2 - 現在將顯示 Visual Studio 的安裝程式。選擇“安裝 Microsoft Visual Studio 2010”

LINQ Environment

步驟 3 - 單擊後,過程將啟動,並在螢幕上顯示一個安裝視窗。載入安裝元件(需要一些時間)完成後,單擊“下一步”按鈕進入下一步。

LINQ Environment

步驟 4 - 這是安裝的最後一步,將出現一個起始頁,只需選擇“我已閱讀並接受許可條款”,然後單擊“下一步”按鈕。

LINQ Environment

步驟 5 - 現在從螢幕上顯示的選項頁面中選擇要安裝的功能。您可以選擇“完全”“自定義”選項。如果您的磁碟空間小於磁碟空間要求中顯示的所需空間,請選擇自定義選項。

LINQ Environment

步驟 6 - 選擇自定義選項時,將出現以下視窗。選擇要安裝的功能,然後單擊“更新”,否則轉到步驟 7。但是,建議不要選擇自定義選項,因為將來您可能需要您選擇不安裝的功能。

LINQ Environment

步驟 7 - 很快將顯示一個彈出視窗,安裝將開始,這可能需要很長時間。請記住,這是安裝所有元件。

LINQ Environment

步驟 8 - 最後,您將能夠在視窗中檢視一條訊息,表明安裝已成功完成。單擊“完成”

LINQ Environment

在 Visual Studio 2010 中使用 LINQ 編寫 C# 程式

  • 啟動 Visual Studio 2010 Ultimate 版本,然後從選單中選擇檔案,然後選擇新建專案。

  • 一個新的專案對話方塊將出現在您的螢幕上。

  • 現在選擇 Visual C# 作為已安裝模板下的類別,然後選擇控制檯應用程式模板,如下圖所示。

LINQ Environment
  • 在底部的名稱框中為您的專案命名,然後按確定。

  • 新的專案將出現在螢幕上新的對話方塊的右側的解決方案資源管理器中。

LINQ Environment
  • 現在從解決方案資源管理器中選擇 Program.cs,您可以在編輯器視窗中檢視程式碼,該程式碼以“using System”開頭。

  • 在這裡,您可以開始編寫以下 C# 程式。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
			
namespace HelloWorld {
   class Program {
      static void Main(string[] args) {
      
         Console.WriteLine("Hello World")
         Console.ReadKey();
      } 		
   }
}
  • 按 F5 鍵執行您的專案。強烈建議在執行專案之前選擇“檔案”“全部儲存”儲存專案。

在 Visual Studio 2010 中使用 LINQ 編寫 VB 程式

  • 啟動 Visual Studio 2010 Ultimate 版本,然後從選單中選擇檔案,然後選擇新建專案。

  • 一個新的專案對話方塊將出現在您的螢幕上。

  • 現在選擇 Visual Basic 作為已安裝模板下的類別,然後選擇控制檯應用程式模板。

  • 在底部的名稱框中為您的專案命名,然後按確定。

  • 您將看到一個包含 Module1.vb 的螢幕。在這裡開始使用 LINQ 編寫 VB 程式碼。

Module Module1

   Sub Main()
      Console.WriteLine("Hello World")
      Console.ReadLine()
   End Sub
   
End Module   
  • 按 F5 鍵執行您的專案。強烈建議在執行專案之前選擇“檔案”“全部儲存”儲存專案。

當編譯並執行上述 C# 或 VB 程式碼時,將產生以下結果:

Hello World

LINQ - 查詢運算子

一組構成查詢模式的擴充套件方法稱為 LINQ 標準查詢運算子。作為 LINQ 查詢表示式的構建塊,這些運算子提供了各種查詢功能,例如篩選、排序、投影、聚合等。

根據其功能,LINQ 標準查詢運算子可以分為以下幾類。

  • 篩選運算子
  • 連線運算子
  • 投影操作
  • 排序運算子
  • 分組運算子
  • 轉換
  • 連線
  • 聚合
  • 量詞操作
  • 分割槽操作
  • 生成操作
  • 集合操作
  • 相等性
  • 元素運算子

篩選運算子

篩選是一種限制結果集的操作,使其只包含滿足特定條件的選定元素。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
where 基於謂詞函式篩選值 where Where
OfType 基於值是否可以轉換為指定型別來篩選值 不適用 不適用

連線運算子

連線是指對資料來源進行操作,這些資料來源之間存在難以直接追蹤的關係。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
Join 該運算子基於匹配的鍵連線兩個序列 join … in … on … equals … From x In …, y In … Where x.a = y.a
GroupJoin 連線兩個序列並分組匹配的元素 join … in … on … equals … into … Group Join … In … On …

投影操作

投影是一種將物件轉換為具有特定屬性的全新形式的操作。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
Select 該運算子基於轉換函式投影值 select Select
SelectMany 該運算子投影基於轉換函式的數值序列,並將它們展平為單個序列 使用多個 from 子句 使用多個 From 子句

排序運算子

排序操作允許基於一個或多個屬性對序列的元素進行排序。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
OrderBy 該運算子按升序排序值 orderby Order By
OrderByDescending 該運算子按降序排序值 orderby ... descending Order By ... Descending
ThenBy 執行二次升序排序 orderby …, … Order By …, …
ThenByDescending 執行二次降序排序 orderby …, … descending Order By …, … Descending
Reverse 反轉集合中元素的順序 不適用 不適用

分組運算子

這些運算子基於共同的共享屬性將資料分成幾組。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
GroupBy 將專案序列組織成組,並將其作為 IGrouping 型別的 IEnumerable 集合返回 group … by -or- group … by … into … Group … By … Into …
ToLookup 執行分組操作,返回鍵值對序列 不適用 不適用

轉換

這些運算子更改輸入物件的型別,並用於各種應用程式。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
AsEnumerable 返回型別為 IEnumerable 的輸入 不適用 不適用
AsQueryable 將 (泛型) IEnumerable 轉換為 (泛型) IQueryable 不適用 不適用
Cast 將集合的元素強制轉換為指定型別 使用顯式型別的範圍變數。例如:from string str in words From … As …
OfType 基於值能否轉換為特定型別來篩選值 不適用 不適用
ToArray 強制執行查詢並將集合轉換為陣列 不適用 不適用
ToDictionary 基於鍵選擇器函式將元素設定為 Dictionary 並強制執行 LINQ 查詢 不適用 不適用
ToList 透過將集合轉換為 List 來強制執行查詢 不適用 不適用
ToLookup 強制執行查詢,並基於鍵選擇器函式將元素放入 Lookup 不適用 不適用

連線

執行兩個序列的連線,其操作與 Union 運算子非常相似,區別在於此操作不刪除重複項。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
Concat 連線兩個序列以形成一個序列。 不適用 不適用

聚合

執行任何型別的所需聚合,並允許在 LINQ 中建立自定義聚合。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
Aggregate 對集合的值進行操作以執行自定義聚合操作 不適用 不適用
Average 計算值集合的平均值 不適用 Aggregate … In … Into Average()
Count 計算集合中滿足謂詞函式的元素個數 不適用 Aggregate … In … Into Count()
LongCount 計算大型集合中滿足謂詞函式的元素個數 不適用 Aggregate … In … Into LongCount()
Max 查詢集合中的最大值 不適用 Aggregate … In … Into Max()
Min 查詢集合中的最小值 不適用 Aggregate … In … Into Min()
Sum 查詢集合中值的總和 不適用 Aggregate … In … Into Sum()

量詞操作

這些運算子在序列中的一些或所有元素滿足特定條件時返回布林值,即 True 或 False。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
All 如果序列的所有元素都滿足謂詞條件,則返回“True”值 不適用 Aggregate … In … Into All(…)
Any 透過搜尋序列來確定序列中的任何元素是否滿足指定條件 不適用 Aggregate … In … Into Any()
Contains 如果找到序列中存在特定元素,則返回“True”值;如果序列不包含該特定元素,則返回“false”值 不適用 不適用

分割槽運算子

將輸入序列分成兩個單獨的部分,而不重新排列序列的元素,然後返回其中一個部分。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
Skip 跳過序列中指定數量的元素,並返回其餘元素 不適用 Skip
SkipWhile 與 Skip 相同,唯一的例外是跳過的元素數量由布林條件指定 不適用 Skip While
Take 從序列中獲取指定數量的元素,並跳過其餘元素 不適用 Take
TakeWhile 與 Take 相同,只是獲取的元素數量由布林條件指定 不適用 Take While

生成操作

生成運算子建立新的值序列。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
DefaultIfEmpty 應用於空序列時,在序列中生成預設元素 不適用 不適用
Empty 返回空值序列,是最簡單的生成運算子 不適用 不適用
Range 生成包含整數或數字序列的集合 不適用 不適用
Repeat 生成包含特定長度重複值的序列 不適用 不適用

集合操作

集合操作共有四個運算子,每個運算子根據不同的標準產生結果。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
Distinct 透過過濾重複資料(如有)從集合中返回唯一值的列表 不適用 Distinct
Except 比較兩個集合的值,並返回一個集合中不在另一個集合中的值 不適用 不適用
Intersect 返回在兩個單獨集合中發現相同的數值集合 不適用 不適用
Union 將兩個不同集合的內容組合成一個列表,並且不包含任何重複內容 不適用 不適用

相等性

比較兩個句子(可列舉的)並確定它們是否完全匹配。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
SequenceEqual 如果發現兩個序列彼此相同,則返回布林值 不適用 不適用

元素運算子

除了 DefaultIfEmpty 之外,其餘八個標準查詢元素運算子都從集合中返回單個元素。

顯示示例

運算子 描述 C# 查詢表示式語法 VB 查詢表示式語法
ElementAt 返回集合中特定索引處的元素 不適用 不適用
ElementAtOrDefault 與 ElementAt 相同,只是在特定索引超出範圍的情況下也返回預設值 不適用 不適用
First 檢索集合中的第一個元素或滿足特定條件的第一個元素 不適用 不適用
FirstOrDefault 與 First 相同,只是在不存在此類元素的情況下也返回預設值 不適用 不適用
Last 檢索集合中的最後一個元素或滿足特定條件的最後一個元素 不適用 不適用
LastOrDefault 與 Last 相同,只是在不存在任何此類元素的情況下也返回預設值 不適用 不適用
Single 返回集合的單個元素或滿足特定條件的單個元素 不適用 不適用
SingleOrDefault 與 Single 相同,只是在不存在任何此類單個元素的情況下也返回預設值 不適用 不適用
DefaultIfEmpty 如果集合或列表為空或為 null,則返回預設值 不適用 不適用

LINQ - SQL

LINQ to SQL 提供了一個基礎結構(執行時)來將關係資料作為物件進行管理。它是 .NET Framework 3.5 版的一個元件,能夠將物件模型的語言整合查詢轉換為 SQL。然後將這些查詢傳送到資料庫以執行。從資料庫獲得結果後,LINQ to SQL 又將其轉換為物件。

LINQ To SQL 簡介

對於大多數 ASP.NET 開發人員來說,LINQ to SQL(也稱為 DLINQ)是語言整合查詢中令人興奮的一部分,因為它允許使用常用的 LINQ 表示式查詢 SQL Server 資料庫中的資料。它也允許更新、刪除和插入資料,但它唯一的缺點是它僅限於 SQL Server 資料庫。但是,與 ADO.NET 相比,LINQ to SQL 有許多好處,例如降低複雜性、減少程式碼行數等等。

下圖顯示了 LINQ to SQL 的執行架構。

LINQ SQL Architecture

如何使用 LINQ to SQL?

步驟 1 − 與資料庫伺服器建立新的“資料連線”。檢視 &arrar; 伺服器資源管理器 &arrar; 資料連線 &arrar; 新增連線

LINQ to SQL

步驟 2 − 新增 LINQ To SQL 類檔案

LINQ to SQL

步驟 3 − 從資料庫中選擇表並將其拖放到新的 LINQ to SQL 類檔案中。

LINQ to SQL

步驟 4 − 將表新增到類檔案中。

LINQ to SQL

使用 LINQ to SQL 查詢

使用 LINQ to SQL 執行查詢的規則與標準 LINQ 查詢類似,即查詢是延遲執行還是立即執行。有各種元件參與 LINQ to SQL 查詢的執行,這些元件如下。

  • LINQ to SQL API − 代表應用程式請求查詢執行,並將其傳送到 LINQ to SQL 提供程式。

  • LINQ to SQL 提供程式 − 將查詢轉換為 Transact SQL(T-SQL),並將新查詢傳送到 ADO 提供程式以執行。

  • ADO 提供程式 − 查詢執行後,將結果以 DataReader 的形式傳送到 LINQ to SQL 提供程式,後者將其轉換為使用者物件的形式。

需要注意的是,在執行 LINQ to SQL 查詢之前,必須透過 DataContext 類連線到資料來源。

使用 LINQ To SQL 進行插入、更新和刪除

新增或插入

C#

using System;
using System.Linq;

namespace LINQtoSQL {
   class LinqToSQLCRUD {
      static void Main(string[] args) {
      
         string connectString = System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnectionString"].ToString();

         LinqToSQLDataContext db = new LinqToSQLDataContext(connectString);           

         //Create new Employee
		 
         Employee newEmployee = new Employee();
         newEmployee.Name = "Michael";
         newEmployee.Email = "yourname@companyname.com";
         newEmployee.ContactNo = "343434343";
         newEmployee.DepartmentId = 3;
         newEmployee.Address = "Michael - USA";

         //Add new Employee to database
         db.Employees.InsertOnSubmit(newEmployee);

         //Save changes to Database.
         db.SubmitChanges();

         //Get new Inserted Employee            
         Employee insertedEmployee = db.Employees.FirstOrDefault(e ⇒e.Name.Equals("Michael"));

         Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3}, Address = {4}",
                          insertedEmployee.EmployeeId, insertedEmployee.Name, insertedEmployee.Email, 
                          insertedEmployee.ContactNo, insertedEmployee.Address);

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Module Module1

   Sub Main()
   
      Dim connectString As String = System.Configuration.ConfigurationManager.ConnectionStrings("LinqToSQLDBConnectionString").ToString()

      Dim db As New LinqToSQLDataContext(connectString)

      Dim newEmployee As New Employee()
	  
      newEmployee.Name = "Michael"
      newEmployee.Email = "yourname@companyname.com"
      newEmployee.ContactNo = "343434343"
      newEmployee.DepartmentId = 3
      newEmployee.Address = "Michael - USA"
     
      db.Employees.InsertOnSubmit(newEmployee)
     
      db.SubmitChanges()
     
      Dim insertedEmployee As Employee = db.Employees.FirstOrDefault(Function(e) e.Name.Equals("Michael"))

      Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3}, 
         Address = {4}", insertedEmployee.EmployeeId, insertedEmployee.Name,
         insertedEmployee.Email, insertedEmployee.ContactNo, insertedEmployee.Address)

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	 
   End Sub
  
End Module

編譯並執行上述 C# 或 VB 程式碼後,將產生以下結果:

Emplyee ID = 4, Name = Michael, Email = yourname@companyname.com, ContactNo = 
343434343, Address = Michael - USA

Press any key to continue.

更新

C#

using System;
using System.Linq;

namespace LINQtoSQL {
   class LinqToSQLCRUD {
      static void Main(string[] args) {
      
         string connectString = System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnectionString"].ToString();

         LinqToSQLDataContext db = new LinqToSQLDataContext(connectString);

         //Get Employee for update
         Employee employee = db.Employees.FirstOrDefault(e =>e.Name.Equals("Michael"));

         employee.Name = "George Michael";
         employee.Email = "yourname@companyname.com";
         employee.ContactNo = "99999999";
         employee.DepartmentId = 2;
         employee.Address = "Michael George - UK";

         //Save changes to Database.
         db.SubmitChanges();

         //Get Updated Employee            
         Employee updatedEmployee = db.Employees.FirstOrDefault(e ⇒e.Name.Equals("George Michael"));

         Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3}, Address = {4}",
                          updatedEmployee.EmployeeId, updatedEmployee.Name, updatedEmployee.Email, 
                          updatedEmployee.ContactNo, updatedEmployee.Address);

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Module Module1

   Sub Main()
  
      Dim connectString As String = System.Configuration.ConfigurationManager.ConnectionStrings("LinqToSQLDBConnectionString").ToString()

      Dim db As New LinqToSQLDataContext(connectString)

      Dim employee As Employee = db.Employees.FirstOrDefault(Function(e) e.Name.Equals("Michael"))

      employee.Name = "George Michael"
      employee.Email = "yourname@companyname.com"
      employee.ContactNo = "99999999"
      employee.DepartmentId = 2
      employee.Address = "Michael George - UK"

      db.SubmitChanges()
          
      Dim updatedEmployee As Employee = db.Employees.FirstOrDefault(Function(e) e.Name.Equals("George Michael"))

      Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3},
         Address = {4}", updatedEmployee.EmployeeId, updatedEmployee.Name, 
         updatedEmployee.Email, updatedEmployee.ContactNo, updatedEmployee.Address)

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	  
   End Sub
   
End Module

編譯並執行上述 C# 或 Vb 程式碼後,將產生以下結果:

Emplyee ID = 4, Name = George Michael, Email = yourname@companyname.com, ContactNo = 
999999999, Address = Michael George - UK

Press any key to continue.

刪除

C#

using System;
using System.Linq;

namespace LINQtoSQL {
   class LinqToSQLCRUD {
      static void Main(string[] args) {
      
         string connectString = System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnectionString"].ToString();

         LinqToSQLDataContext db = newLinqToSQLDataContext(connectString);

         //Get Employee to Delete
         Employee deleteEmployee = db.Employees.FirstOrDefault(e ⇒e.Name.Equals("George Michael"));

         //Delete Employee
         db.Employees.DeleteOnSubmit(deleteEmployee);

         //Save changes to Database.
         db.SubmitChanges();

         //Get All Employee from Database
         var employeeList = db.Employees;
         foreach (Employee employee in employeeList) {
            Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3}",
               employee.EmployeeId, employee.Name, employee.Email, employee.ContactNo);
         }            

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Module Module1

   Sub Main()
   
      Dim connectString As String = System.Configuration.ConfigurationManager.ConnectionStrings("LinqToSQLDBConnectionString").ToString()

      Dim db As New LinqToSQLDataContext(connectString)

      Dim deleteEmployee As Employee = db.Employees.FirstOrDefault(Function(e) e.Name.Equals("George Michael"))

      db.Employees.DeleteOnSubmit(deleteEmployee)

      db.SubmitChanges()

      Dim employeeList = db.Employees
	  
      For Each employee As Employee In employeeList
         Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2}, ContactNo = {3}",
            employee.EmployeeId, employee.Name, employee.Email, employee.ContactNo)
      Next 

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
   End Sub
   
End Module

編譯並執行上述 C# 或 VB 程式碼後,將產生以下結果:

Emplyee ID = 1, Name = William, Email = abc@gy.co, ContactNo = 999999999
Emplyee ID = 2, Name = Miley, Email = amp@esds.sds, ContactNo = 999999999
Emplyee ID = 3, Name = Benjamin, Email = asdsad@asdsa.dsd, ContactNo = 

Press any key to continue.

LINQ - 物件

LINQ to Objects 允許使用任何支援 IEnumerable 的 LINQ 查詢來訪問記憶體中的資料集合,而無需像 LINQ to SQL 或 LINQ to XML 那樣使用 LINQ 提供程式 (API)。

LINQ to Objects 簡介

LINQ to Objects 查詢通常只返回 `IEnumerable` 型別的變數。簡而言之,LINQ to Objects 提供了一種全新的集合處理方法。以前,需要編寫冗長的程式碼(複雜的 foreach 迴圈)才能從集合中檢索資料,而現在則可以使用宣告性程式碼清晰地描述所需檢索的資料。

與傳統的 foreach 迴圈相比,LINQ to Objects 還有許多優點,例如可讀性更強、過濾功能更強大、能夠進行分組、排序功能增強且應用程式程式碼最少。這種 LINQ 查詢也更簡潔,並且可以無需修改或只需少量修改即可移植到任何其他資料來源。

下面是一個簡單的 LINQ to Objects 示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LINQtoObjects {
   class Program {
      static void Main(string[] args) {
      
         string[] tools = { "Tablesaw", "Bandsaw", "Planer", "Jointer", "Drill", "Sander" };
         var list = from t in tools select t;

         StringBuilder sb = new StringBuilder();

         foreach (string s in list) {
            sb.Append(s + Environment.NewLine);
         }
		 
         Console.WriteLine(sb.ToString(), "Tools");
         Console.ReadLine();
      }
   }
}

在此示例中,字串陣列(tools)用作使用 LINQ to Objects 查詢的物件集合。

Objects query is:
var list = from t in tools select t;

當編譯並執行上述程式碼時,將產生以下結果:

Tablesaw
Bandsaw
Planer
Jointer
Drill
Sander

使用 LINQ to Objects 查詢記憶體集合

C#

using System;
using System.Collections.Generic;
using System.Linq;

namespace LINQtoObjects {
   class Department {
      public int DepartmentId { get; set; }
      public string Name { get; set; }
   }

   class LinqToObjects {
      static void Main(string[] args) {
      
         List<Department> departments = new List<Department>();
			
         departments.Add(new Department { DepartmentId = 1, Name = "Account" });
         departments.Add(new Department { DepartmentId = 2, Name = "Sales" });
         departments.Add(new Department { DepartmentId = 3, Name = "Marketing" });

         var departmentList = from d in departments
                              select d;

         foreach (var dept in departmentList) {
            Console.WriteLine("Department Id = {0} , Department Name = {1}",
               dept.DepartmentId, dept.Name);
         }
		 
         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Collections.Generic
Imports System.Linq

Module Module1

   Sub Main(ByVal args As String())

      Dim account As New Department With {.Name = "Account", .DepartmentId = 1}
      Dim sales As New Department With {.Name = "Sales", .DepartmentId = 2}
      Dim marketing As New Department With {.Name = "Marketing", .DepartmentId = 3}

      Dim departments As New System.Collections.Generic.List(Of Department)(New Department() {account, sales, marketing})

      Dim departmentList = From d In departments

      For Each dept In departmentList
         Console.WriteLine("Department Id = {0} , Department Name = {1}", dept.DepartmentId, dept.Name)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
   End Sub

   Class Department
      Public Property Name As String
      Public Property DepartmentId As Integer
   End Class
   
End Module

當編譯並執行上述 C# 或 VB 程式碼時,將產生以下結果:

Department Id = 1, Department Name = Account
Department Id = 2, Department Name = Sales
Department Id = 3, Department Name = Marketing

Press any key to continue.

LINQ - 資料集

資料集提供了一種極其有用的記憶體中資料表示形式,並用於各種基於資料應用程式。作為 LINQ to ADO.NET 技術之一,LINQ to DataSet 以輕鬆的方式促進對資料集資料執行查詢,並提高生產力。

LINQ To DataSet 簡介

LINQ to DataSet 簡化了開發人員的查詢任務。他們不需要使用特定的查詢語言編寫查詢,而是可以使用程式語言編寫相同的查詢。LINQ to DataSet 也可用於查詢來自多個數據源的整合資料。這也不需要任何 LINQ 提供程式,就像 LINQ to SQL 和 LINQ to XML 用於訪問記憶體集合中的資料一樣。

下面是一個簡單的 LINQ to DataSet 查詢示例,其中首先獲取資料來源,然後用兩個資料表填充資料集。在兩個表之間建立關係,並使用連線子句針對兩個表建立 LINQ 查詢。最後,使用 foreach 迴圈顯示所需的結果。

C#

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LINQtoDataset {
   class Program {
      static void Main(string[] args) {
      
         string connectString = System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnectionString"].ToString();

         string sqlSelect = "SELECT * FROM Department;" + "SELECT * FROM Employee;";

         // Create the data adapter to retrieve data from the database
         SqlDataAdapter da = new SqlDataAdapter(sqlSelect, connectString);
        
         // Create table mappings
         da.TableMappings.Add("Table", "Department");
         da.TableMappings.Add("Table1", "Employee");

         // Create and fill the DataSet
         DataSet ds = new DataSet();
         da.Fill(ds);

         DataRelation dr = ds.Relations.Add("FK_Employee_Department",
                           ds.Tables["Department"].Columns["DepartmentId"],
                           ds.Tables["Employee"].Columns["DepartmentId"]);

         DataTable department = ds.Tables["Department"];
         DataTable employee = ds.Tables["Employee"];

         var query = from d in department.AsEnumerable()
                     join e in employee.AsEnumerable()
                     on d.Field<int>("DepartmentId") equals
                     e.Field<int>("DepartmentId")                        
                     select new {
                        EmployeeId = e.Field<int>("EmployeeId"),
                        Name = e.Field<string>("Name"),                            
                        DepartmentId = d.Field<int>("DepartmentId"),                            
                        DepartmentName = d.Field<string>("Name")
                     };

         foreach (var q in query) {
            Console.WriteLine("Employee Id = {0} , Name = {1} , Department Name = {2}",
               q.EmployeeId, q.Name, q.DepartmentName);
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Data.SqlClient
Imports System.Linq

Module LinqToDataSet

   Sub Main()
   
      Dim connectString As String = System.Configuration.ConfigurationManager.ConnectionStrings("LinqToSQLDBConnectionString").ToString()

      Dim sqlSelect As String = "SELECT * FROM Department;" + "SELECT * FROM Employee;"
      Dim sqlCnn As SqlConnection = New SqlConnection(connectString)
      sqlCnn.Open()

      Dim da As New SqlDataAdapter
      da.SelectCommand = New SqlCommand(sqlSelect, sqlCnn)

      da.TableMappings.Add("Table", "Department")
      da.TableMappings.Add("Table1", "Employee")

      Dim ds As New DataSet()
      da.Fill(ds)

      Dim dr As DataRelation = ds.Relations.Add("FK_Employee_Department", ds.Tables("Department").Columns("DepartmentId"), ds.Tables("Employee").Columns("DepartmentId"))

      Dim department As DataTable = ds.Tables("Department")
      Dim employee As DataTable = ds.Tables("Employee")

      Dim query = From d In department.AsEnumerable()
                  Join e In employee.AsEnumerable() On d.Field(Of Integer)("DepartmentId") Equals
                  e.Field(Of Integer)("DepartmentId")
                  Select New Person With { _
                        .EmployeeId = e.Field(Of Integer)("EmployeeId"),
                        .EmployeeName = e.Field(Of String)("Name"),
                        .DepartmentId = d.Field(Of Integer)("DepartmentId"),
                        .DepartmentName = d.Field(Of String)("Name")
                  }

      For Each e In query
         Console.WriteLine("Employee Id = {0} , Name = {1} , Department Name = {2}", e.EmployeeId, e.EmployeeName, e.DepartmentName)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	  
   End Sub
  
   Class Person
      Public Property EmployeeId As Integer
      Public Property EmployeeName As String
      Public Property DepartmentId As Integer
      Public Property DepartmentName As String
   End Class
   
End Module

當編譯並執行上述 C# 或 VB 程式碼時,將產生以下結果:

Employee Id = 1, Name = William, Department Name = Account
Employee Id = 2, Name = Benjamin, Department Name = Account
Employee Id = 3, Name = Miley, Department Name = Sales

Press any key to continue.

使用 LinQ to DataSet 查詢資料集

在開始使用 LINQ to DataSet 查詢資料集之前,必須將資料載入到資料集,這可以透過使用 DataAdapter 類或 LINQ to SQL 來完成。使用 LINQ to DataSet 編寫查詢的方式與使用 LINQ 以及其他支援 LINQ 的資料來源編寫查詢的方式非常相似。

單表查詢

在下面的單表查詢中,從 SalesOrderHeaderTtable 收集所有線上訂單,然後顯示訂單 ID、訂單日期以及訂單號作為輸出。

C#

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LinqToDataset {
   class SingleTable {
      static void Main(string[] args) {
      
         string connectString = System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnectionString"].ToString();

         string sqlSelect = "SELECT * FROM Department;";

         // Create the data adapter to retrieve data from the database
         SqlDataAdapter da = new SqlDataAdapter(sqlSelect, connectString);

         // Create table mappings
         da.TableMappings.Add("Table", "Department");           

         // Create and fill the DataSet
         DataSet ds = new DataSet();
         da.Fill(ds);

         DataTable department = ds.Tables["Department"];            

         var query = from d in department.AsEnumerable()                        
         select new {
            DepartmentId = d.Field<int>("DepartmentId"),
            DepartmentName = d.Field<string>("Name")
         };

         foreach (var q in query) {
            Console.WriteLine("Department Id = {0} , Name = {1}",
               q.DepartmentId, q.DepartmentName);
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Data.SqlClient
Imports System.Linq

Module LinqToDataSet

   Sub Main()
   
      Dim connectString As String = System.Configuration.ConfigurationManager.ConnectionStrings("LinqToSQLDBConnectionString").ToString()

      Dim sqlSelect As String = "SELECT * FROM Department;"
      Dim sqlCnn As SqlConnection = New SqlConnection(connectString)
      sqlCnn.Open()

      Dim da As New SqlDataAdapter
      da.SelectCommand = New SqlCommand(sqlSelect, sqlCnn)

      da.TableMappings.Add("Table", "Department")
      Dim ds As New DataSet()
      da.Fill(ds)

      Dim department As DataTable = ds.Tables("Department")

      Dim query = From d In department.AsEnumerable()
      Select New DepartmentDetail With {
         .DepartmentId = d.Field(Of Integer)("DepartmentId"),
            .DepartmentName = d.Field(Of String)("Name")
      }

      For Each e In query
         Console.WriteLine("Department Id = {0} , Name = {1}", e.DepartmentId, e.DepartmentName)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
   End Sub

   Public Class DepartmentDetail
      Public Property DepartmentId As Integer
      Public Property DepartmentName As String
   End Class
   
End Module

當編譯並執行上述 C# 或 VB 程式碼時,將產生以下結果:

Department Id = 1, Name = Account
Department Id = 2, Name = Sales
Department Id = 3, Name = Pre-Sales
Department Id = 4, Name = Marketing

Press any key to continue.

LINQ - XML

LINQ to XML 提供對所有 LINQ 功能(如標準查詢運算子、程式設計介面等)的輕鬆訪問。LINQ to XML 整合在 .NET 框架中,還充分利用了 .NET 框架的功能,例如除錯、編譯時檢查、強型別等。

LINQ to XML 簡介

使用 LINQ to XML 時,可以輕鬆地將 XML 文件載入到記憶體中,更輕鬆地進行查詢和文件修改。還可以將記憶體中存在的 XML 文件儲存到磁碟並對其進行序列化。它使開發人員無需學習相對複雜的 XML 查詢語言。

LINQ to XML 的強大功能體現在 System.Xml.Linq 名稱空間中。它包含所有 19 個必要的類來處理 XML。這些類如下所示。

  • XAttribute
  • XCData
  • XComment
  • XContainer
  • XDeclaration
  • XDocument
  • XDocumentType
  • XElement
  • XName
  • XNamespace
  • XNode
  • XNodeDocumentOrderComparer
  • XNodeEqualityComparer
  • XObject
  • XObjectChange
  • XObjectChangeEventArgs
  • XObjectEventHandler
  • XProcessingInstruction
  • XText

使用 LINQ 讀取 XML 檔案

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace LINQtoXML {
   class ExampleOfXML {
      static void Main(string[] args) {
      
         string myXML = @"<Departments>
                       <Department>Account</Department>
                       <Department>Sales</Department>
                       <Department>Pre-Sales</Department>
                       <Department>Marketing</Department>
                       </Departments>";

         XDocument xdoc = new XDocument();
         xdoc = XDocument.Parse(myXML);

         var result = xdoc.Element("Departments").Descendants();

         foreach (XElement item in result) {
            Console.WriteLine("Department Name - " + item.Value);
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Collections.Generic
Imports System.Linq
Imports System.Xml.Linq

Module Module1

   Sub Main(ByVal args As String())
   
      Dim myXML As String = "<Departments>" & vbCr & vbLf & 
                           "<Department>Account</Department>" & vbCr & vbLf & 
                           "<Department>Sales</Department>" & vbCr & vbLf & 
                           "<Department>Pre-Sales</Department>" & vbCr & vbLf & 
                           "<Department>Marketing</Department>" & vbCr & vbLf & 
                           "</Departments>"

      Dim xdoc As New XDocument()
      xdoc = XDocument.Parse(myXML)

      Dim result = xdoc.Element("Departments").Descendants()

      For Each item As XElement In result
         Console.WriteLine("Department Name - " + item.Value)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	  
   End Sub
   
End Module

當編譯並執行上述 C# 或 VB 程式碼時,將產生以下結果:

Department Name - Account
Department Name - Sales
Department Name - Pre-Sales
Department Name - Marketing

Press any key to continue. 

新增新節點

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace LINQtoXML {
   class ExampleOfXML {
      static void Main(string[] args) {
      
         string myXML = @"<Departments>
                       <Department>Account</Department>
                       <Department>Sales</Department>
                       <Department>Pre-Sales</Department>
                       <Department>Marketing</Department>
                       </Departments>";

         XDocument xdoc = new XDocument();
         xdoc = XDocument.Parse(myXML);

         //Add new Element
         xdoc.Element("Departments").Add(new XElement("Department", "Finance"));

         //Add new Element at First
         xdoc.Element("Departments").AddFirst(new XElement("Department", "Support"));

         var result = xdoc.Element("Departments").Descendants();

         foreach (XElement item in result) {
            Console.WriteLine("Department Name - " + item.Value);
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Collections.Generic
Imports System.Linq
Imports System.Xml.Linq

Module Module1

   Sub Main(ByVal args As String())
   
      Dim myXML As String = "<Departments>" & vbCr & vbLf & 
     	                   "<Department>Account</Department>" & vbCr & vbLf & 
     	                   "<Department>Sales</Department>" & vbCr & vbLf & 
     	                   "<Department>Pre-Sales</Department>" & vbCr & vbLf & 
     	                   "<Department>Marketing</Department>" & vbCr & vbLf & 
     	                   "</Departments>"

      Dim xdoc As New XDocument()
      xdoc = XDocument.Parse(myXML)

      xdoc.Element("Departments").Add(New XElement("Department", "Finance"))
     
      xdoc.Element("Departments").AddFirst(New XElement("Department", "Support"))

      Dim result = xdoc.Element("Departments").Descendants()

      For Each item As XElement In result
         Console.WriteLine("Department Name - " + item.Value)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	  
   End Sub
   
End Module

當編譯並執行上述 C# 或 VB 程式碼時,將產生以下結果:

Department Name - Support
Department Name - Account
Department Name - Sales
Department Name - Pre-Sales
Department Name - Marketing
Department Name - Finance

Press any key to continue.

刪除特定節點

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace LINQtoXML {
   class ExampleOfXML {
      static void Main(string[] args) {
      
         string myXML = @"<Departments>
                       <Department>Support</Department>
                       <Department>Account</Department>
                       <Department>Sales</Department>
                       <Department>Pre-Sales</Department>
                       <Department>Marketing</Department>
                       <Department>Finance</Department>
                       </Departments>";

         XDocument xdoc = new XDocument();
         xdoc = XDocument.Parse(myXML);

         //Remove Sales Department
         xdoc.Descendants().Where(s =>s.Value == "Sales").Remove(); 

         var result = xdoc.Element("Departments").Descendants();

         foreach (XElement item in result) {
            Console.WriteLine("Department Name - " + item.Value);
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

VB

Imports System.Collections.Generic
Imports System.Linq
Imports System.Xml.Linq

Module Module1

   Sub Main(args As String())
   
      Dim myXML As String = "<Departments>" & vbCr & vbLf & 
     	                   "<Department>Support</Department>" & vbCr & vbLf & 
     	                   "<Department>Account</Department>" & vbCr & vbLf & 
     	                   "<Department>Sales</Department>" & vbCr & vbLf & 
     	                   "<Department>Pre-Sales</Department>" & vbCr & vbLf & 
     	                   "<Department>Marketing</Department>" & vbCr & vbLf & 
     	                   "<Department>Finance</Department>" & vbCr & vbLf & 
                           "</Departments>"

      Dim xdoc As New XDocument()
      xdoc = XDocument.Parse(myXML)
     
      xdoc.Descendants().Where(Function(s) s.Value = "Sales").Remove()

      Dim result = xdoc.Element("Departments").Descendants()

      For Each item As XElement In result
         Console.WriteLine("Department Name - " + item.Value)
      Next

      Console.WriteLine(vbLf & "Press any key to continue.")
      Console.ReadKey()
	  
   End Sub
   
End Module

當編譯並執行上述 C# 或 VB 程式碼時,將產生以下結果:

Department Name - Support
Department Name - Account
Department Name - Pre-Sales
Department Name - Marketing
Department Name - Finance

Press any key to continue. 

LINQ - 實體

LINQ to Entities 作為 ADO.NET Entity Framework 的一部分,比 LINQ to SQL 更靈活,但由於其複雜性和缺乏關鍵功能而並不流行。但是,它沒有 LINQ to SQL 的侷限性,後者只允許在 SQL Server 資料庫中查詢資料,而 LINQ to Entities 則可以方便地在大量資料提供程式(如 Oracle、MySQL 等)中查詢資料。

此外,它得到了 ASP.Net 的主要支援,使用者可以使用資料來源控制元件透過 LINQ to Entities 執行查詢,並無需額外編碼即可繫結結果。

由於這些優勢,LINQ to Entities 如今已成為在資料庫中使用 LINQ 的標準機制。使用 LINQ to Entities 還可以輕鬆更改查詢資料的詳細資訊並提交批次更新。LINQ to Entities 最引人注目的事實是它具有與 SQL 相同的語法,甚至具有相同的標準查詢運算子組,如 Join、Select、OrderBy 等。

LINQ to Entities 查詢建立和執行過程

  • 從 **ObjectContext**(實體連線)構建 **ObjectQuery** 例項

  • 使用新構建的例項使用 C# 或 Visual Basic (VB) 編寫查詢

  • 將 LINQ 的標準查詢運算子以及 LINQ 表示式轉換為命令樹

  • 執行查詢,並將遇到的任何異常直接傳遞給客戶端

  • 將所有查詢結果返回給客戶端

**ObjectContext** 是這裡的主要類,它能夠與 **Entity Data Model** 互動,或者換句話說,它充當連線 LINQ 和資料庫的橋樑。命令樹是此處與 Entity Framework 相容的查詢表示。

另一方面,Entity Framework 實際上是 **物件關係對映器**,開發人員通常將其縮寫為 ORM,它根據資料庫表生成業務物件和實體,並促進建立、更新、刪除和讀取等各種基本操作。下圖顯示了實體框架及其元件。

LINQ - Entities

使用 LINQ 和實體模型進行 ADD、UPDATE 和 DELETE 的示例

首先按照以下步驟新增實體模型。

**步驟 1** - 右鍵單擊專案並單擊“新增新項”將開啟如下所示的視窗。選擇 ADO.NET 實體資料模型,指定名稱,然後單擊“新增”。

LINQ - Entity Model

**步驟 2** - 選擇 **從資料庫生成**。

LINQ - Entity Model

**步驟 3** - 從下拉選單中選擇資料庫連線。

LINQ - Entity Model

**步驟 4** - 選擇所有表。

LINQ - Entity Model

現在編寫以下程式碼。

using DataAccess;
using System;
using System.Linq;

namespace LINQTOSQLConsoleApp {
   public class LinqToEntityModel {
      static void Main(string[] args) {

         using (LinqToSQLDBEntities context = new LinqToSQLDBEntities()) {
            //Get the List of Departments from Database
            var departmentList = from d in context.Departments
            select d;

            foreach (var dept in departmentList) {
               Console.WriteLine("Department Id = {0} , Department Name = {1}",
                  dept.DepartmentId, dept.Name);
            }

            //Add new Department
            DataAccess.Department department = new DataAccess.Department();
            department.Name = "Support";

            context.Departments.Add(department);
            context.SaveChanges();

            Console.WriteLine("Department Name = Support is inserted in Database");

            //Update existing Department
            DataAccess.Department updateDepartment = context.Departments.FirstOrDefault(d ⇒d.DepartmentId == 1);
            updateDepartment.Name = "Account updated";
            context.SaveChanges();

            Console.WriteLine("Department Name = Account is updated in Database");

            //Delete existing Department
            DataAccess.Department deleteDepartment = context.Departments.FirstOrDefault(d ⇒d.DepartmentId == 3);
            context.Departments.Remove(deleteDepartment);
            context.SaveChanges();

            Console.WriteLine("Department Name = Pre-Sales is deleted in Database");

            //Get the Updated List of Departments from Database
            departmentList = from d in context.Departments
            select d;

            foreach (var dept in departmentList) {
               Console.WriteLine("Department Id = {0} , Department Name = {1}",
                  dept.DepartmentId, dept.Name);
            }
         }

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

當編譯並執行上述程式碼時,將產生以下結果:

LINQ - Entity Model Result

LINQ - Lambda 表示式

術語“Lambda 表示式”來源於“lambda 演算”,後者是一種用於定義函式的數學符號。作為 LINQ 方程的可執行部分,Lambda 表示式以執行時的方式轉換邏輯,以便可以方便地將其傳遞給資料來源。但是,Lambda 表示式不僅限於在 LINQ 中使用。

這些表示式由以下語法表示:

(Input parameters) ⇒ Expression or statement block

這是一個 Lambda 表示式的示例:

y ⇒ y * y

上述表示式指定了一個名為 y 的引數,並且 y 的值是平方。但是,無法以這種形式執行 Lambda 表示式。下面顯示了 C# 中 Lambda 表示式的示例。

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {

      delegate int del(int i);
      static void Main(string[] args) {

         del myDelegate = y ⇒ y * y;
         int j = myDelegate(5);
         Console.WriteLine(j);
         Console.ReadLine();
      }
   }
}

VB

Module Module1
   Private Delegate Function del(ByVal i As Integer) As Integer
   
   Sub Main(ByVal args As String())
   
      Dim myDelegate As del = Function(y) y * y
      Dim j As Integer = myDelegate(5)
      Console.WriteLine(j)
      Console.ReadLine()
	  
   End Sub
   
End Module

當編譯並執行上述 C# 或 VB 程式碼時,將產生以下結果:

25

表示式 Lambda

由於上述 Lambda 表示式語法的表示式位於右側,因此它們也被稱為表示式 Lambda。

非同步 Lambda

透過使用 async 關鍵字結合非同步處理建立的 Lambda 表示式稱為非同步 Lambda。下面是一個非同步 Lambda 的示例。

Func<Task<string>> getWordAsync = async()⇒ “hello”;

標準查詢運算子中的 Lambda

查詢運算子中的 Lambda 表示式由同一個按需計算,並持續處理輸入序列中的每個元素,而不是整個序列。Lambda 表示式允許開發人員將自己的邏輯輸入標準查詢運算子。在下面的示例中,開發人員使用了“Where”運算子,透過使用 Lambda 表示式從給定的列表中取回奇數值。

C#

//Get the average of the odd Fibonacci numbers in the series... 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {     
      static void Main(string[] args) {
      
         int[] fibNum = { 1, 1, 2, 3, 5, 8, 13, 21, 34 };
         double averageValue = fibNum.Where(num ⇒ num % 2 == 1).Average();
         Console.WriteLine(averageValue);
         Console.ReadLine();
      }
   }
}

VB

Module Module1

   Sub Main()
   
      Dim fibNum As Integer() = {1, 1, 2, 3, 5, 8, 13, 21, 34}
      Dim averageValue As Double = fibNum.Where(Function(num) num Mod 2 = 1).Average()
	  
      Console.WriteLine(averageValue)
      Console.ReadLine()
	  
   End Sub
   
End Module

當編譯並執行上述程式碼時,將產生以下結果:

7.33333333333333

Lambda 中的型別推斷

在 C# 中,型別推斷可以方便地用於各種情況下,而且無需顯式指定型別。但是,對於 Lambda 表示式,型別推斷僅在已指定每個型別時才有效,因為編譯器必須得到滿足。讓我們考慮以下示例。

delegate int Transformer (int i);

編譯器在這裡使用型別推斷來推斷 x 是一個整數,這是透過檢查 Transformer 的引數型別來完成的。

Lambda 表示式中的變數作用域

在 Lambda 表示式中使用變數作用域時有一些規則,例如在 Lambda 表示式中初始化的變數不能在外部方法中可見。還有一個規則是,除非引用它的委託有資格進行垃圾回收,否則捕獲的變數不會被垃圾回收。此外,還有一條規則禁止 Lambda 表示式中的 return 語句導致封閉方法返回。

這是一個演示 Lambda 表示式中變數作用域的示例。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {
      delegate bool D();
      delegate bool D2(int i);

      class Test {
         D del;
         D2 del2;
			
         public void TestMethod(int input) {
            int j = 0;
            // Initialize the delegates with lambda expressions.
            // Note access to 2 outer variables.
            // del will be invoked within this method.
            del = () ⇒ { j = 10; return j > input; };

            // del2 will be invoked after TestMethod goes out of scope.
            del2 = (x) ⇒ { return x == j; };

            // Demonstrate value of j:            
            // The delegate has not been invoked yet.
            Console.WriteLine("j = {0}", j);        // Invoke the delegate.
            bool boolResult = del();
           
            Console.WriteLine("j = {0}. b = {1}", j, boolResult);
         }

         static void Main() {
            Test test = new Test();
            test.TestMethod(5);

            // Prove that del2 still has a copy of
            // local variable j from TestMethod.
            bool result = test.del2(10);
           
            Console.WriteLine(result);

            Console.ReadKey();
         }
      }
   }
}

當編譯並執行上述程式碼時,將產生以下結果:

j = 0
j = 10. b = True
True

表示式樹

Lambda 表示式廣泛用於 **表示式樹** 的構建。表示式樹以類似樹的資料結構提供程式碼,其中每個節點本身就是一個表示式,例如方法呼叫,或者可以是二元運算,例如 x

語句 Lambda

還有 **語句 Lambda**,它包含兩到三個語句,但不用於構建表示式樹。必須在語句 Lambda 中編寫 return 語句。

語句 Lambda 的語法

(params)⇒ {statements}

語句 Lambda 的示例

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace lambdaexample {
   class Program {
      static void Main(string[] args) {
         int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };

         foreach (int i in source.Where(x ⇒ 
            {
               if (x <= 3)
                  return true;
               else if (x >= 7)
                  return true;
               return false;
            }
         ))
        Console.WriteLine(i);
        Console.ReadLine();
      }
   }
}

當編譯並執行上述程式碼時,將產生以下結果:

3
8
1
7
9
2
8

Lambda 用作基於方法的 LINQ 查詢中的引數,並且不允許像匿名方法一樣位於運算子(如 **is** 或 **as**)的左側。雖然 Lambda 表示式與匿名方法非常相似,但它們並不侷限於僅用作委託。

使用 Lambda 表示式時需要注意的事項

  • Lambda 表示式可以返回值,並且可以有引數。

  • 可以使用多種方式在 Lambda 表示式中定義引數。

  • 如果 Lambda 表示式中只有一個語句,則不需要花括號;如果有多個語句,則需要編寫花括號和返回值。

  • 使用 Lambda 表示式,可以透過稱為閉包的功能訪問 Lambda 表示式塊外部存在的變數。應謹慎使用閉包,以免出現任何問題。

  • 無法在任何 Lambda 表示式內執行任何不安全的程式碼。

  • Lambda 表示式不能用於運算子的左側。

LINQ - ASP.Net

作為一組 .NET 框架擴充套件,LINQ 是 ASP.NET 開發人員首選的資料訪問機制。ASP.NET 3.5 內建了一個 LINQDataSource 控制元件,可以輕鬆地在 ASP.NET 中使用 LINQ。ASP.NET 使用上述控制元件作為資料來源。現實專案大多包含網站或 Windows 應用程式,因此為了更好地理解 ASP.NET 中 LINQ 的概念,讓我們從建立一個使用 LINQ 功能的 ASP.NET 網站開始。

為此,必須在您的系統上安裝 Visual Studio 和 .NET 框架。開啟 Visual Studio 後,轉到檔案 → 新建 → 網站。將開啟一個彈出視窗,如下所示。

LINQ - ASP.Net

現在,在左側的模板下,將有兩個語言選項可用於建立網站。選擇 **Visual C#** 並選擇 **ASP.NET 空網站**。

選擇要在系統上儲存新網站的資料夾。然後按 **確定**,很快 **解決方案資源管理器** 將出現在您的螢幕上,其中包含所有 Web 檔案。右鍵單擊解決方案資源管理器中的 Default.aspx,然後選擇在瀏覽器中檢視,以在瀏覽器中檢視預設的 ASP.NET 網站。很快,您的新 ASP.NET 網站將在 Web 瀏覽器中開啟,如下面的螢幕截圖所示。

LINQ - ASP.Net

.aspx 事實上是 ASP.NET 網站中使用的主要副檔名。Visual Studio 預設情況下會為基本的網站建立所有必要的頁面,例如 **主頁** 和 **關於我們** 頁面,您可以在其中方便地放置您的內容。網站的程式碼在此處自動生成,也可以檢視。

LINQDataSource 控制元件

藉助 LINQDataSource 控制元件,可以在 ASP.NET 網站的頁面中 **更新、插入** 和 **刪除** 資料。完全無需指定 SQL 命令,因為 LINQDataSource 控制元件會為這類操作採用動態生成的命令。

該控制元件使使用者可以透過標記文字中的屬性設定,方便地在 ASP.NET 網頁中使用 LINQ。LINQDataSource 與 **SqlDataSource** 和 **ObjectDataSource** 等控制元件非常相似,因為它可以用於將頁面上存在的其他 ASP.NET 控制元件繫結到資料來源。因此,我們必須擁有一個 **資料庫** 來解釋 LINQDataSource 控制元件呼叫的各種函式。

在開始解釋在 ASP.NET 網頁表單中使用該控制元件之前,必須開啟 Microsoft Visual Studio 工具箱並將 LINQDataSource 控制元件拖放到 ASP.NET 網站的 .aspx 頁面上,如下圖所示。

LINQ - ASP.Net

下一步是配置 LINQDataSource,選擇員工記錄的所有列。

LINQ - ASP.Net

現在,向 .aspx 頁面新增 GridView 控制元件並對其進行配置,如下圖所示。GridView 控制元件功能強大,並提供處理資料的靈活性。配置控制元件後,它將很快出現在瀏覽器中。

LINQ - ASP.Net

現在可以在螢幕上檢視 .aspx 頁面的程式碼:

<!DOCTYPE html>

<html>
   <head runat = "server">
      <title></title>
   </head>

   <body>
      <form id = "form1" runat = "server">
         <div>
            <asp:GridView ID = "GridView1" runat = "server" AutoGenerateColumns = "False"
			
               DataKeyNames = "ContactID" DataSourceID = "LINQDataSource1">
               <Columns>
			   
                  <asp:BoundField DataField = "ContactID" HeaderText = "ContactID"
                     InsertVisible = "False" ReadOnly="True" SortExpression = "ContactID" />
                  <asp:CheckBoxField DataField = "NameStyle" HeaderText = "NameStyle"
                     SortExpression = "NameStyle" />
                  <asp:BoundField DataField = "Title" HeaderText = "Title" SortExpression = "Title" />
                  <asp:BoundField DataField = "FirstName" HeaderText = "FirstName"
                     SortExpression="FirstName" />
                  <asp:BoundField DataField = "MiddleName" HeaderText = "MiddleName"
                     SortExpression = "MiddleName" />
                  <asp:BoundField DataField = "LastName" HeaderText = "LastName"
                     SortExpression = "LastName" />
                  <asp:BoundField DataField = "Suffix" HeaderText = "Suffix"
                     SortExpression = "Suffix" />
                  <asp:BoundField DataField = "EmailAddress" HeaderText = "EmailAddress"
                     SortExpression = "EmailAddress" />
               </Columns>

            </asp:GridView>

            <br />

         </div>

         <asp:LINQDataSource ID = "LINQDataSource1" runat = "server"

            ContextTypeName = "LINQWebApp1.AdventureWorksDataContext" EntityTypeName = ""
               TableName = "Contacts">

         </asp:LINQDataSource>
      </form>
   </body>
</html>

這裡應該注意的是,必須將 ContextTypeName 屬性設定為表示資料庫的類的屬性。例如,這裡將其設定為 LINQWebApp1.AdventureWorksDataContext,因為此操作將建立 LINQDataSource 和資料庫之間的必要連線。

使用 LINQ 在 ASP.NET 頁面中插入、更新和刪除資料

嚴格完成上述所有步驟後,從 **LINQDataSource 控制元件** 中選擇 **LINQDataSource 任務**,並從其中選擇所有三個複選框以啟用插入、啟用更新和啟用刪除,如下圖所示。

LINQ - ASP.Net

很快,宣告性標記將顯示在您的螢幕上,如下所示。

<asp:LINQDataSource 
   ContextTypeName = "LINQWebApp1.AdventureWorksDataContext" 
   TableName = "Contacts" 
   EnableUpdate = "true" 
   EnableInsert = "true" 
   EnableDelete = "true" 
   ID = "LINQDataSource1" 
   runat = "server">
</asp:LINQDataSource>

現在,由於有多行和多列,最好在 .aspx 表單上新增另一個名為“詳細資訊檢視”或“主控制元件”的控制元件,該控制元件位於 GridView 控制元件下方,以僅顯示所選網格行的詳細資訊。從“詳細資訊檢視”控制元件中選擇“詳細資訊檢視任務”,然後選擇如下所示的複選框。

LINQ - ASP.Net

現在,只需儲存更改並按 Ctrl + F5 即可在瀏覽器中檢視頁面,現在可以在詳細資訊檢視控制元件上刪除、更新和插入任何記錄。

廣告
© . All rights reserved.