LINQ 簡介
Language-integrated Query (LINQ) (LINQ) 是 Visual Studio 2008 和 .NET Framework 3.5 版中引入的一項創新功能。
傳統上,針對資料的查詢都是以簡單的字串表示,而沒有編譯時間類型檢查或 IntelliSense 支援。此外,您還必須針對以下各種資料來源學習一種不同的查詢語言:SQL 資料庫、XML 文檔、各種 Web 服務等等。 通過LINQ, 您可以使用語言關鍵字和熟悉的運算子針對強型別化對象集合編寫查詢。
在 Visual Studio 中,可以為以下資料來源編寫 LINQ 查詢:SQL Server 資料庫、XML 文檔、ADO.NET 資料集,以及支援 IEnumerable 或泛型 IEnumerable<T> 介面的任意對象集合。
使用要求:項目 ≥ .NET Framework 3.5 。
一、介紹 LINQ 查詢
查詢是一種從資料來源檢索資料的運算式。隨著時間的推移,人們已經為各種資料來源開發了不同的語言;例如,用於關聯式資料庫的 SQL 和用於 XML 的 XQuery。因此,開發人員不得不針對他們必須支援的每種資料來源或資料格式而學習新的查詢語言。
LINQ 通過提供一種跨資料來源和資料格式使用資料的一致模型,簡化了這一情況。在 LINQ 查詢中,始終會用到對象。可以使用相同的編碼模式來查詢和轉換 XML 文檔、SQL 資料庫、ADO.NET 資料集、.NET 集合中的資料以及對其有 LINQ 提供者可用的任何其他格式的資料。
1.1 查詢操作的三個部分
操作三部曲:①取資料來源 ②建立查詢 ③執行查詢
internal class Program{ private static void Main(string[] args) { //1.擷取資料來源 var nums = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; //2.建立查詢 var numQuery = from num in nums where (num % 2) == 0 select num; //3.執行查詢 foreach (var num in numQuery) { Console.WriteLine("{0}", num); } }}
結果:
0246
顯示了完整的查詢操作。在 LINQ 中,查詢的執行與查詢本身截然不同;換句話說,查詢本身指的是只建立查詢變數,不檢索任何資料。
1.2 資料來源
在上一個樣本中,由於資料來源是數組,因此它隱式支援泛型 IEnumerable<T> 介面。支援 IEnumerable<T> 或派生介面(如泛型 IQueryable<T>)的類型稱為可查詢型別。
可查詢型別不需要進行修改或特殊處理就可以用作 LINQ 資料來源。如果來源資料還沒有作為可查詢型別出現在記憶體中,則 LINQ 提供者必須以此方式表示來源資料。例如,LINQ to XML 將 XML 文檔載入到可查詢的 XElement 類型中:
//從 XML 中建立資料來源//using System.Xml.Linq;var contacts = XElement.Load(@"c:\xxx.xml");
在 LINQ to SQL 中,首先需要建立對象關係映射。 針對這些對象編寫查詢,然後由 LINQ to SQL 在運行時處理與資料庫的通訊。
var db = new Northwnd(@"c:\northwnd.mdf");//查詢在倫敦的客戶var custQuery= from cust in db.Customers where cust.City == "London" select cust;
Customers 表示資料庫中的特定表
1.3 查詢
查詢指定要從資料來源中檢索的資訊。 查詢還可以指定在返回這些資訊之前如何對其進行排序、分組和結構化。 查詢儲存在查詢變數中,並用查詢運算式進行初始化。
之前的樣本中的查詢是從整數數組中返回所有的偶數。 該查詢運算式包含三個子句:from、where 和 select。(如果您熟悉 SQL,您會注意到這些子句的順序與 SQL 中的順序相反。)from 子句指定資料來源,where 子句指定應用篩選器,select 子句指定返回的元素的類型。 目前需要注意的是,在 LINQ 中,查詢變數本身不執行任何操作並且不返回任何資料。 它只是儲存在以後某個時刻執行查詢時為產生結果而必需的資訊。
1.4 查詢執行
1.順延強制
如前所述,查詢變數本身只是儲存查詢命令。 實際的查詢執行會延遲到在 foreach 語句中逐一查看查詢變數時發生。 此概念稱為“順延強制”。
2.強制立即執行
對一系列源元素執資料列彙總函式的查詢必須首先逐一查看這些元素。Count、Max、Average 和 First 就屬於此類查詢。由於查詢本身必須使用 foreach 以便返回結果,因此這些查詢在執行時不使用顯式 foreach 語句。另外還要注意,這些類型的查詢返回單個值,而不是 IEnumerable 集合。
var numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var evenNumQuery = from num in numbers where (num % 2) == 0 select num; var evenNumCount = evenNumQuery.Count();
結果:
4
若要強制立即執行任意查詢並緩衝其結果,可以調用 ToList<TSource> 或 ToArray<TSource> 方法。
var numQuery2 =(from num in numbers where (num % 2) == 0 select num).ToList(); var numQuery3 =(from num in numbers where (num % 2) == 0 select num).ToArray();
此外,還可以通過在緊跟查詢運算式之後的位置放置一個 foreach 迴圈來強制執行查詢。但是,通過調用 ToList 或 ToArray,也可以將所有資料緩衝在單個集合對象中。
二、基本 LINQ 查詢操作
2.1 擷取資料來源:from
在 LINQ 查詢中,第一步是指定資料來源。像在大多數程式設計語言中一樣,必須先聲明變數,才能使用它。在 LINQ 查詢中,最先使用 from 子句的目的是引入資料來源和範圍變數。
//queryAllCustomers 是 IEnumerable<Cutsomer> 類型//資料來源 (customers) 和範圍變數 (cust)var queryAllCustomers = from cust in customers select cust;
範圍變數類似於 foreach 迴圈中的迭代變數,但在查詢運算式中,實際上不發生迭代。執行查詢時,範圍變數將用作對 customers 中的每個後續元素的引用。因為編譯器可以推斷 cust 的類型,所以您不必顯式指定此類型。
2.2 篩選:where
也許最常用的查詢操作是應用布林運算式形式的篩選器。此篩選器使查詢只返回那些運算式結果為 true 的元素。使用 where 子句產生結果。實際上,篩選器指定從源序列中排除哪些元素。
var queryLondonCustomers = from cust in customers where cust.City = "London" select cust;
您可以使用熟悉的 C# 邏輯 AND(&&)和 OR(||) 運算子來根據需要在 where 子句中應用任意數量的篩選條件運算式。
where cust.City = "London" && cust.Name = "Devon"where cust.City = "London" || cust.Name = "Paris"
2.3 排序:orderby
通常可以很方便地將返回的資料進行排序。orderby 子句將使返回的序列中的元素按照被排序的類型的預設比較子進行排序。
var queryLondonCustomers = from cust in customers where cust.City = "London" orderby cust.Name descending select cust;
因為 Name 是一個字串,所以預設比較子執行從 A 到 Z 的字母排序。若要按相反順序(從 Z 到 A)對結果進行排序,請使用 orderby…descending 子句。
2.4 分組:group
使用 group 子句,您可以按指定的鍵分組結果。
var queryLondonCustomers = from cust in customers group cust by cust.City; foreach (var queryLondonCustomer in queryLondonCustomers) { Console.WriteLine(queryLondonCustomer.Key); foreach (var cust in queryLondonCustomer) { Console.WriteLine(cust.Name); } }
您可以指定結果應按 City 分組,以便位於倫敦或巴黎的所有客戶位於各自組中。
在本例中,cust.City 是鍵。
在使用 group 子句結束查詢時,結果採用列表的列表形式。列表中的每個元素是一個具有 Key 成員及根據該鍵分組的元素列表的對象。在逐一查看產生組序列的查詢時,您必須使用嵌套的 foreach 迴圈。外部迴圈用於逐一查看每個組,內部迴圈用於逐一查看每個組的成員。
如果您必須引用組操作的結果,可以使用 into 關鍵字來建立可進一步查詢的標識符。
//custQuery 是 IEnumable<IGrouping<string, Customer>> 類型 var custQuery = from cust in customers group cust by cust.City into custGroup where custGroup.Count() > 2 orderby custGroup.Key select custGroup;
這裡的查詢只返回那些包含兩個以上的客戶的組。
2.5 聯結:join
聯結運算建立資料來源中沒有顯式建模的序列之間的關聯。例如,您可以執行聯結來尋找位於同一地點的所有客戶和經銷商。在 LINQ 中,join 子句始終針對對象集合而非直接針對資料庫表運行。
var innerJoinQuery = from cust in customers join dist in distributors on cust.City equals dist.City select new {CustomerName = cust.Name, DistributorName = dist.Name};
在 LINQ 中,join 子句始終針對對象集合而非直接針對資料庫表運行。
在 LINQ 中,您不必像在 SQL 中那樣頻繁使用 join,因為 LINQ 中的外鍵在物件模型中表示為包含項集合的屬性。
from order in Customer.Orders...
2.6 選擇(投影):select
select 子句產生查詢結果並指定每個返回的元素的“形狀”或類型。
例如,您可以指定結果包含的是整個 Customer 對象、僅一個成員、成員的子集,還是某個基於計算或新對象建立的完全不同的結果類型。當 select 子句產生除源元素副本以外的內容時,該操作稱為“投影”。
三、使用 LINQ 進行資料轉換
Language-integrated Query (LINQ) (LINQ) 不僅可用於檢索資料,而且還是一個功能強大的資料轉換工具。通過使用 LINQ 查詢,您可以將源序列用作輸入,並採用多種方式修改它以建立新的輸出序列。您可以通過排序和分組來修改該序列,而不必修改元素本身。但是,LINQ 查詢的最強大的功能是能夠建立新類型。這一功能在 select 子句中實現。 例如,可以執行下列任務:
3.1 將多個輸入聯結到一個輸出序列
class Student { public string Name { get; set; } public int Age { get; set; } public string City { get; set; } public List<int> Scores { get; set; } } class Teacher { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string City { get; set; } }
學生和老師兩個類
internal class Program { private static void Main(string[] args) { //建立第一個資料來源 var students = new List<Student>() { new Student() { Age = 23, City = "廣州", Name = "小C", Scores = new List<int>(){85,88,83,97} }, new Student() { Age = 18, City = "廣西", Name = "小明", Scores = new List<int>(){86,78,85,90} }, new Student() { Age = 33, City = "夢裡", Name = "小三", Scores = new List<int>(){86,68,73,97} } }; //建立第二個資料來源 var teachers = new List<Teacher>() { new Teacher() { Age = 35, City = "夢裡", Name = "啵哆" }, new Teacher() { Age = 28, City = "雲南", Name = "小紅" }, new Teacher() { Age = 38, City = "河南", Name = "麗麗" } }; //建立查詢 var peopleInDreams = (from student in students where student.City == "夢裡" select student.Name) .Concat(from teacher in teachers where teacher.City == "夢裡" select teacher.Name); //執行查詢 foreach (var person in peopleInDreams) { Console.WriteLine(person); } Console.Read(); } }
以上就是C#開始使用 LINQ (上)的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!