日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LINQ 的标准查询操作符

發布時間:2025/3/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LINQ 的标准查询操作符 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
摘自msdn (http://msdn.microsoft.com/zh-cn/magazine/cc337893.aspx)
LINQ 的標準查詢操作符 John Papa
代碼下載位置: DataPoints2008_03.exe (958 KB)
Browse the Code Online 目錄 操作符和 LINQ
操作符類型
Lambda 表達式
First 和 Single
聚合、層次結構和投影
投影和排序
限定符和轉換
結束語

語言集成查詢 (LINQ) 允許開發人員通過強類型化語法使用 Microsoft? .NET Framework 3.5 代碼編寫類似 SQL 的查詢。然后,各種 LINQ 提供程序,如 LINQ to Objects(可利用它根據對象層次結構編寫查詢)和 LINQ to Entities(可利用它根據實體框架的概念模型編寫查詢)可根據代表數據存儲的細微差別來有效處理這些查詢。 除強類型化語法外,LINQ 查詢還具有一個標準查詢操作符庫來增強其功能。這些標準查詢操作符對序列進行運算并可執行各種運算,如確定序列中是否存在某個值以及對序列運行合計函數(如求和)。 在本月的專欄中,我將使用 LINQ 來執行實際的查詢和運算(會用到 LINQ to Objects 和 LINQ to Entities)。我將查詢一個實體集合并使用其導航屬性深入研究一組具備層次結構的實體。我還會為您演示如何對數組和集合應用多個標準查詢操作符。并展示如何使用 lambda 表達式強化 LINQ 的標準查詢操作符,以及如何利用它們來從序列解析特定信息并對序列執行復雜的邏輯運算。本專欄的下載中提供有所有代碼示例(請參見 msdn.microsoft.com/msdnmag/code08.aspx)。
操作符和 LINQ LINQ 自身功能非常強大,無論使用的是 LINQ to XML、LINQ to DataSets、LINQ to Entities、LINQ to Objects 還是附帶的任何其他 LINQ 提供程序。LINQ 的核心功能在于其強類型化查詢語法,它可用于任意此類提供程序。當將 LINQ 與一個或多個標準查詢操作符結合使用時,會得到一個功能更為強大的工具集,從而可精細地控制一組數據。 標準查詢操作符在 System.Linq 命名空間中的 System.Core.dll 程序集中作為靜態類 Enumerable 和 Queryable 的擴展方法存在,并且可用于實現 IEnumerable<T> 或 IQueryable<T> 的對象。這樣它們就能使用 LINQ to Entities 和 LINQ to SQL 之類的提供程序對各類對象執行運算,從內存中的集合和數組(序列)到遠程數據庫。 可輕松地確定處理特定任務時所擁有的操作符。如果要在 LINQ 查詢中使用操作符,可使用 Queryable 靜態類可用擴展方法中的操作符。如果要對實現 IEnumerable<T> 的序列使用操作符,可使用 Enumerable 靜態類中的一個擴展方法。但是,請記住:并非 Queryable 類中的所有操作符都適用于基礎數據存儲,因此運行時可能不支持某些操作符。
操作符類型 操作符有多種類型(使用對象瀏覽器查看 Enumerable 和 Queryable 類即可找到所有操作符)。圖 A 以字母順序顯示了不同類型操作符的分類??衫盟鼇泶笾铝私庖幌虏僮鞣峁┑墓δ?。我將使用 LINQ to Objects 和 LINQ to Entities 展示一小組此類操作符,以顯示它們如何為實際應用程序帶來好處。 Figure?A?Categories of Operators
操作符說明
聚合?
Aggregate對序列執行一個自定義方法
Average計算數值序列的平均值
Count返回序列中的項目數(整數)
LongCount返回序列中的項目數(長型)
Min查找數字序列中的最小數
Max查找數字序列中的最大數
Sum匯總序列中的數字
連接?
Concat將兩個序列連成一個序列
轉換?
Cast將序列中的元素轉換成指定類型
OfType篩選序列中指定類型的元素
ToArray從序列返回一個數組
ToDictionary從序列返回一個字典
ToList從序列返回一個列表
ToLookup從序列返回一個查詢
ToSequence返回一個 IEnumerable 序列
元素?
DefaultIfEmpty為空序列創建默認元素
ElementAt返回序列中指定索引的元素
ElementAtOrDefault返回序列中指定索引的元素,或者如果索引超出范圍,則返回默認值
First返回序列中的第一個元素
FirstOrDefault返回序列中的第一個元素,或者如果未找到元素,則返回默認值
Last返回序列中的最后一個元素
LastOrDefault返回序列中的最后一個元素,或者如果未找到元素,則返回默認值
Single返回序列中的單個元素
SingleOrDefault返回序列中的單個元素,或者如果未找到元素,則返回默認值
相等?
SequenceEqual比較兩個序列看其是否相等
生成?
Empty生成一個空序列
Range生成一個指定范圍的序列
Repeat通過將某個項目重復指定次數來生成一個序列
分組?
GroupBy按指定分組方法對序列中的項目進行分組
聯接?
GroupJoin通過歸組將兩個序列聯接在一起
Join將兩個序列從內部聯接起來
排序?
OrderBy以升序按值排列序列
OrderByDescending以降序按值排列序列
ThenBy升序排列已排序的序列
ThenByDescending降序排列已排序的序列
Reverse顛倒序列中項目的順序
分區?
Skip返回跳過指定數目項目的序列
SkipWhile返回跳過不滿足表達式項目的序列
Take返回具有指定數目項目的序列
TakeWhile返回具有滿足表達式項目的序列
投影?
Select創建部分序列的投影
SelectMany創建部分序列的一對多投影
限定符?
All確定序列中的所有項目是否滿足某個條件
Any確定序列中是否有任何項目滿足條件
Contains確定序列是否包含指定項目
限制?
Where篩選序列中的項目
設置?
Distinct返回無重復項目的序列
Except返回代表兩個序列差集的序列
Intersect返回代表兩個序列交集的序列
Union返回代表兩個序列交集的序列

Lambda 表達式 許多標準查詢操作符在對序列執行運算時都使用 Func 委托來處理單個元素。Lambda 表達式可與標準查詢操作符結合使用以代表委托。lambda 表達式是創建委托實現的簡略表達形式,并可用于匿名委托適用的所有場合。C# 和 Visual Basic? .NET 均支持 Lambda 表達式。但是,必須注意:由于 Visual Basic .NET 尚不支持匿名方法,Lambda 表達式可能僅包含一個語句。 讓我們來看看如何對一個整數數組使用 Single 操作符。這個整數數組的每個元素代表 2 的 1 到 10 次方。先創建此數組,然后使用 Single 操作符來檢索滿足 Lambda 表達式中指定條件的單個整數元素: int[] nums = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 }; int singleNum = nums.Single(x => x > 16 && x < 64); Console.WriteLine(singleNum.ToString()); Lambda 表達式包含多個關鍵部分。Lambda 表達式首先定義傳入委托的變量。在以上代碼示例中,x(在 => 操作符左側聲明)是參數,代表傳遞給它的 nums 數組中的每個元素。Lambda 表達式的剩余部分代表數組中每個元素的評估邏輯。可使用匿名委托輕松地重新編寫以上表達式,如下所示: ? int singleNum = nums.Single<int>( delegate(int x) {return (x > 16 && x < 64); } ) ; 但是,此代碼的可讀性不及 Lambda 表達式。C# 2.0 引入了可使委托的傳遞稍微輕松些的匿名委托;但是,Lambda 表達式的簡潔語法可使其更加簡單。
First 和 Single 如果必須從序列中提取一個值,First、FirstOrDefault、Single 和 SingleOrDefault 操作符都非常有用。First 方法返回序列中的第一個元素。First 有一個重載方法,可使用它來傳入 Lambda 表達式來代表一個條件。例如,如果要返回整數序列中整數元素大于 50 的第一個元素,可使用以下代碼示例: ? int[] nums = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 }; int num1 = nums.First<int>(); int num2 = nums.First<int>(x => x > 50); int num3 = nums.FirstOrDefault<int>(x => x > 5000); Console.WriteLine( num1.ToString() + "-" + num2.ToString() + "-" + num3.ToString()); 此代碼會查找第一個元素 (1)、大于 50 的第一個元素 (64) 以及大于 5,000 的第一個元素。由于數組中沒有元素滿足第三個 Lambda 表達式(數組中無整數大于 5,000),則如果代碼使用的是 First 操作符而非 FirstOrDefault,則會引發異常。在使用 FirstOrDefault 操作符時,如果沒有元素滿足 Lambda 表達式,則會返回 0。First 操作符也可用于 LINQ to Entities 查詢,如下所示: ? using (Entities entities = new Entities()) { var query = (from c in entities.Customers select c).First(c => c.City.Equals("London")); Console.WriteLine(query.CompanyName); } 在此示例中,將返回 London 城中的第一個客戶。正如您所看到的,當 First 方法用于各種 LINQ 提供程序(在本例中為 LINQ to Objects 和 LINQ to Entities)時,所用的語法并不會更改。 在 LINQ to Entities 上下文中,First 操作符非常有用,尤其是您知道會從查詢返回單個記錄時。例如,您可能有個查詢,它常在給出 CustomerID 時獲取一條客戶記錄。這種情況總是返回 0 或 1 條記錄,因此,得到一個序列不如就得到一個實體本身。換句話說,您寧愿獲取 Customer 實體而非 1 個 Customer 實體序列。First 方法在某種怦下非常有用,如以下代碼段所示。(由于實體框架不會嘗試在客戶端和服務器之間分發單個查詢的執行,并且 LINQ to Entities 不支持 Single 方法,因此使用 First 方法是個輕松的替代方法。) ? using (Entities entities = new Entities()) { var query = (from c in entities.Customers where c.CustomerID.Equals("BOLID") select c).First(); Console.WriteLine(query.CompanyName); }
聚合、層次結構和投影 在 LINQ to Entities 查詢中使用聚合操作符(如 Sum)可有助于簡化查詢。例如,以下代碼檢索訂單總額大于 $10,000 的一個訂單序列: ? using (Entities entities = new Entities()) { var query = from o in entities.Orders where o.OrderDetails.Sum( od => od.UnitPrice * od.Quantity) >= 10000 select o; foreach (Orders order in query) Console.WriteLine(order.OrderID); } 由于 LINQ 可查詢層次結構實體集合,因此標準查詢操作符也可用于對嵌套實體序列執行運算。當必須計算或詢問派生數據時,這一點非常有用。派生數據可能僅存在于其基本窗體中,如客戶訂單的詳細信息僅包含單價和數量值。在本例中,未在模型中的任何位置提供代表訂單總金額的聚合數據。然而,通過在 LINQ 查詢中應用 Sum 操作符,仍可檢索消費金額超過 $20,000 的所有客戶,如下所示: ? using (Entities entities = new Entities()) { var query = from c in entities.Customers where c.Orders.Sum( o => o.OrderDetails.Sum( od => od.UnitPrice * od.Quantity)) >= 25000 select c; foreach (Customers customer in query) Console.WriteLine(customer.CompanyName); } 此示例展示了如何在 LINQ 查詢的多個層次應用標準查詢操作符。查詢最終會返回一個 Customers 實體序列,但為達到此目的,它必須首先深入每個客戶的訂單以及每個訂單的訂單詳細信息獲取所需數據,這樣才可以計算每項的價格,匯總每個訂單的項目,然后匯總每個客戶的總額。 Count 操作符是另一聚合標準查詢操作符??赏ㄟ^使用以下代碼確定有多少客戶的消費金額超過 $25,000: ? using (Entities entities = new Entities()) { var query = (from c in entities.Customers where c.Orders.Sum( o => o.OrderDetails.Sum( od => od.UnitPrice * od.Quantity)) >= 25000 select c).Count(); Console.WriteLine(query); } 可使用 Max 操作符來確定最佳客戶。以下代碼示例將返回消費最高的客戶所花費的金額。它在層次結構的多個層級中組合使用 Sum 和 Max 聚合操作符: using (Entities entities = new Entities()) { var query = (from c in entities.Customers select new { c.CustomerID, Total = c.Orders.Sum( o => o.OrderDetails.Sum(od => od.UnitPrice)) }).Max(c2 => c2.Total); Console.WriteLine(query); }
投影和排序 您可能還注意到我在之前的示例中暗藏了一個投影。在使用 Max 操作符之前,LINQ 查詢并不返回客戶列表。而是會返回一個投影,此投影創建了包含 CustomerID 屬性和 Total 屬性(客戶的整個消費金額)的一個新實體。投影是 LINQ 必不可少的一部分,如前一示例所示,將它們投影到序列中后,就可使用標準查詢操作符來進一步處理它們。 圖 1 顯示了如何創建一個新實體投影,其中包含 CustomerID 和客戶的訂單總金額(使用之前討論的 Sum 操作符)。圖 1 還使用 OrderByDescending 操作符來按計算總額對投影實體序列進行排序。如果兩個客戶總額相同,還會使用另一排序操作符來進一步定義順序。例如,還可使用以下代碼修正圖 1 中的 foreach 語句以進一步限定排序規則: ?Figure?1?Aggregates, Projections, and Ordering 復制代碼 using (Entities entities = new Entities()) { var query = from c in entities.Customers where c.Orders.Sum( o => o.OrderDetails.Sum(od => od.UnitPrice)) > 0 select new { c.CustomerID, Total = c.Orders.Sum( o => o.OrderDetails.Sum(od => od.UnitPrice)) }; foreach (var item in query.OrderByDescending(x => x.Total)) Console.WriteLine(item.CustomerID + " == " + item.Total); } foreach (var item in query.OrderByDescending(x => x.Total) .ThenBy(x => x.CustomerID)) { Console.WriteLine(item.CustomerID + " == " + item.Total); } 在該代碼段中,我添加了 ThenBy 操作符和一個 Lambda 表達式,以表示序列應首先按 Total 屬性降序排列,然后按投影的 CustomerID 屬性升序排列。
限定符和轉換 如果需要確定序列中是否存在某個值,可使用標準查詢操作符 Any。限定符(如 Any、All 和 Contains)會搜索元素序列,并評估序列是否滿足 lambda 表達式的條件。如果需檢查序列以確定某些事宜(例如:是否存在來自特定地址的客戶、所有客戶是否來自同一國家或者任意其他分析確定性問題),它將非常有用。 例如,以下 LINQ 查詢會檢查是否來自 United Kingdom 的所有客戶都位于 London。它使用限定符 All 并將其傳遞給僅評估城市是否為 London 的 lambda 表達式。如果序列中的每個元素都滿足此條件并且 lambda 表達式返回 true,然后 All 操作符會返回 true: using (Entities entities = new Entities()) { bool allUKCustomerAreFromLondon = (from c in entities.Customers where c.Country == "UK" select c).All( c => c.City.Equals("London")); Console.WriteLine(allUKCustomerAreFromLondon ? "Yes" : "No"); } 需在此查詢中詢問的另一問題是序列中是否有來自 United Kingdom 的 Cowes 的實體。對于此問題,可使用 Any 限定符來計算序列,如下所示: using (Entities entities = new Entities()) { bool isOneUKCustomerFromCowes = (from c in entities.Customers where c.Country == "UK" select c).Any( c => c.City.Equals("Cowes")); Console.WriteLine(isOneUKCustomerFromCowes? "Yes" : "No"); } Contains 操作符在評估序列中是否包括您所查找的項目時類似于 Any 操作符。Any 操作符可確定序列的某個項中是否存在某個值,而 Contains 操作符則確定序列中是否存在特定項目實例。例如,在將某個對象添加到序列中之前,您可能希望確保序列中并未包含該對象。圖 2 展示了如何檢查。 ?Figure?2?Using Contains and Conversion using (Entities entities = new Entities()) { Customers customerBSBEV = (from c in entities.Customers where c.CustomerID == "BSBEV" select c).First(); var customersUK = from c in entities.Customers where c.Country == "UK" select c; bool isCustomerInSequence = customersUK.Contains(customerBSBEV); Console.WriteLine(isCustomerInSequence? "Yes" : "No"); } 請注意:在圖 2 中,首先針對 BSBEV 客戶檢索 Customers 實體。然后,檢索客戶來自 United Kingdom 的 Customers 實體序列。最后,使用 Contains 操作符來檢查 Customers 序列是否包含 customerBSBEV 變量的實例。 圖 2 中所顯示的 Contains 操作符實現適用于可基于其實際實例信心十足地比較對象的場合。但是,如果需要 Contains 操作符根據邏輯標識進行測試又該如何呢?幸運的是,Contains 操作符包含一個重載,可使用它來傳遞實現 IEqualityComparer<T> 接口的對象。要根據 CustomerID 使用 Contains,可按如下所示重新編寫圖 2 中的代碼: using (Entities entities = new Entities()) { ... bool isCustomerInSequence = customersUK.Contains(customerBSBEV, new CustomerComparer()); Console.WriteLine(isCustomerInSequence? "Yes" : "No"); } 其中 CustomerComparer 定義為 ? private class CustomerComparer : IEqualityComparer<Customers> { public bool Equals(Customers x, Customers y) { if (x == null || y == null) return false; return x.CustomerID.Equals(y.CustomerID); } ... }
結束語 有許多標準查詢操作符均可定義為 Enumerable 和 Queryable 序列類的擴展方法。如我之前所示,這些操作符有助于擴展 LINQ 的功能。我還展示了結合使用多個 .NET Framework 3.5 新增強功能(包括 lambda 表達式、LINQ、實體框架和隱式類型化變量)來更加輕松地編寫功能強大的代碼和邏輯。

請將您想向 John 詢問的問題和提出的意見發送至?mmdatat@microsoft.com.


John Papa 是 ASPSOFT (aspsoft.com) 的一位資深 .NET 顧問,同時也是一位狂熱的棒球迷,在夏季的大多數夜晚,他都與家人以及忠實的狗 Kadi 一起為洋基隊加油。John 是 C# 領域的一位 MVP 和 INETA 發言人,撰寫過多本有關數據訪問技術方面的書籍。他經常在行業會議上發表演講,或者在 http://www.johnpapa.net/ 上撰寫博客文章。

轉載于:https://www.cnblogs.com/lxydmq/archive/2008/05/29/1209834.html

總結

以上是生活随笔為你收集整理的LINQ 的标准查询操作符的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。