日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
詳解LINQ標(biāo)準(zhǔn)查詢操作符

LINQ對于開發(fā)人員來說很方便,不過掌握LINQ的標(biāo)準(zhǔn)查詢操作符是基礎(chǔ)中的基礎(chǔ)。本文將為大家詳細(xì)講解LINQ標(biāo)準(zhǔn)查詢操作符的用法,希望對大家有所幫助。語言集成查詢 (LINQ) 允許開發(fā)人員通過強(qiáng)類型化語法使用 Microsoft? .NET Framework 3.5 代碼編寫類似 SQL 的查詢。然后,各種 LINQ 提供程序,如 LINQ to Objects(可利用它根據(jù)對象層次結(jié)構(gòu)編寫查詢)和 LINQ to Entities(可利用它根據(jù)實(shí)體框架的概念模型編寫查詢)可根據(jù)代表數(shù)據(jù)存儲的細(xì)微差別來有效處理這些查詢。

#T#

除強(qiáng)類型化語法外,LINQ 查詢還具有一個(gè)標(biāo)準(zhǔn)查詢操作符庫來增強(qiáng)其功能。這些標(biāo)準(zhǔn)查詢操作符對序列進(jìn)行運(yùn)算并可執(zhí)行各種運(yùn)算,如確定序列中是否存在某個(gè)值以及對序列運(yùn)行合計(jì)函數(shù)(如求和)。

在本月的專欄中,我將使用 LINQ 來執(zhí)行實(shí)際的查詢和運(yùn)算(會(huì)用到 LINQ to Objects 和 LINQ to Entities)。我將查詢一個(gè)實(shí)體集合并使用其導(dǎo)航屬性深入研究一組具備層次結(jié)構(gòu)的實(shí)體。我還會(huì)為您演示如何對數(shù)組和集合應(yīng)用多個(gè)標(biāo)準(zhǔn)查詢操作符。并展示如何使用 lambda 表達(dá)式強(qiáng)化 LINQ 的標(biāo)準(zhǔn)查詢操作符,以及如何利用它們來從序列解析特定信息并對序列執(zhí)行復(fù)雜的邏輯運(yùn)算。本專欄的下載中提供有所有代碼示例(請參見 msdn.microsoft.com/msdnmag/code08.aspx)。

操作符和 LINQ

LINQ 自身功能非常強(qiáng)大,無論使用的是 LINQ to XML、LINQ to DataSets、LINQ to Entities、LINQ to Objects 還是附帶的任何其他 LINQ 提供程序。LINQ 的核心功能在于其強(qiáng)類型化查詢語法,它可用于任意此類提供程序。當(dāng)將 LINQ 與一個(gè)或多個(gè)標(biāo)準(zhǔn)查詢操作符結(jié)合使用時(shí),會(huì)得到一個(gè)功能更為強(qiáng)大的工具集,從而可精細(xì)地控制一組數(shù)據(jù)。

標(biāo)準(zhǔn)查詢操作符在 System.Linq 命名空間中的 System.Core.dll 程序集中作為靜態(tài)類 Enumerable 和 Queryable 的擴(kuò)展方法存在,并且可用于實(shí)現(xiàn) IEnumerable 或 IQueryable 的對象。這樣它們就能使用 LINQ to Entities 和 LINQ to SQL 之類的提供程序?qū)Ω黝悓ο髨?zhí)行運(yùn)算,從內(nèi)存中的集合和數(shù)組(序列)到遠(yuǎn)程數(shù)據(jù)庫。

可輕松地確定處理特定任務(wù)時(shí)所擁有的操作符。如果要在 LINQ 查詢中使用操作符,可使用 Queryable 靜態(tài)類可用擴(kuò)展方法中的操作符。如果要對實(shí)現(xiàn) IEnumerable 的序列使用操作符,可使用 Enumerable 靜態(tài)類中的一個(gè)擴(kuò)展方法。但是,請記?。翰⒎?Queryable 類中的所有操作符都適用于基礎(chǔ)數(shù)據(jù)存儲,因此運(yùn)行時(shí)可能不支持某些操作符。

操作符類型

操作符有多種類型(使用對象瀏覽器查看 Enumerable 和 Queryable 類即可找到所有操作符)。以字母順序顯示了不同類型操作符的分類。可利用它來大致了解一下操作符所提供的功能。我將使用 LINQ to Objects 和 LINQ to Entities 展示一小組此類操作符,以顯示它們?nèi)绾螢閷?shí)際應(yīng)用程序帶來好處。

FigureACategories of Operators

Lambda 表達(dá)式

許多標(biāo)準(zhǔn)查詢操作符在對序列執(zhí)行運(yùn)算時(shí)都使用 Func 委托來處理單個(gè)元素。Lambda 表達(dá)式可與標(biāo)準(zhǔn)查詢操作符結(jié)合使用以代表委托。lambda 表達(dá)式是創(chuàng)建委托實(shí)現(xiàn)的簡略表達(dá)形式,并可用于匿名委托適用的所有場合。C# 和 Visual Basic? .NET 均支持 Lambda 表達(dá)式。但是,必須注意:由于 Visual Basic .NET 尚不支持匿名方法,Lambda 表達(dá)式可能僅包含一個(gè)語句。

讓我們來看看如何對一個(gè)整數(shù)數(shù)組使用 Single 操作符。這個(gè)整數(shù)數(shù)組的每個(gè)元素代表 2 的 1 到 10 次方。先創(chuàng)建此數(shù)組,然后使用 Single 操作符來檢索滿足 Lambda 表達(dá)式中指定條件的單個(gè)整數(shù)元素:

 
 
  1. int[] nums = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 };  
  2. int singleNum = nums.Single(x => x > 16 && x < 64);  
  3. Console.WriteLine(singleNum.ToString()); 

Lambda 表達(dá)式包含多個(gè)關(guān)鍵部分。Lambda 表達(dá)式首先定義傳入委托的變量。在以上代碼示例中,x(在 => 操作符左側(cè)聲明)是參數(shù),代表傳遞給它的 nums 數(shù)組中的每個(gè)元素。Lambda 表達(dá)式的剩余部分代表數(shù)組中每個(gè)元素的評估邏輯??墒褂媚涿休p松地重新編寫以上表達(dá)式,如下所示:

 
 
  1. int singleNum = nums.Single(  
  2. delegate(int x) {return (x > 16 && x < 64); }  
  3. ) ; 

但是,此代碼的可讀性不及 Lambda 表達(dá)式。C# 2.0 引入了可使委托的傳遞稍微輕松些的匿名委托;但是,Lambda 表達(dá)式的簡潔語法可使其更加簡單。

First 和 Single

如果必須從序列中提取一個(gè)值,F(xiàn)irst、FirstOrDefault、Single 和 SingleOrDefault 操作符都非常有用。First 方法返回序列中的***個(gè)元素。First 有一個(gè)重載方法,可使用它來傳入 Lambda 表達(dá)式來代表一個(gè)條件。例如,如果要返回整數(shù)序列中整數(shù)元素大于 50 的***個(gè)元素,可使用以下代碼示例:

 
 
  1. int[] nums = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 };  
  2. int num1 = nums.First();  
  3. int num2 = nums.First(x => x > 50);  
  4. int num3 = nums.FirstOrDefault(x => x > 5000);  
  5. Console.WriteLine(  
  6. num1.ToString() + "-" +  
  7. num2.ToString() + "-" +  
  8. num3.ToString()); 

此代碼會(huì)查找***個(gè)元素 (1)、大于 50 的***個(gè)元素 (64) 以及大于 5,000 的***個(gè)元素。由于數(shù)組中沒有元素滿足第三個(gè) Lambda 表達(dá)式(數(shù)組中無整數(shù)大于 5,000),則如果代碼使用的是 First 操作符而非 FirstOrDefault,則會(huì)引發(fā)異常。在使用 FirstOrDefault 操作符時(shí),如果沒有元素滿足 Lambda 表達(dá)式,則會(huì)返回 0。First 操作符也可用于 LINQ to Entities 查詢,如下所示:

 
 
  1. using (Entities entities = new Entities())  
  2. {  
  3. var query = (from c in entities.Customers  
  4. select c).First(c => c.City.Equals("London"));  
  5. Console.WriteLine(query.CompanyName);  

在此示例中,將返回 London 城中的***個(gè)客戶。正如您所看到的,當(dāng) First 方法用于各種 LINQ 提供程序(在本例中為 LINQ to Objects 和 LINQ to Entities)時(shí),所用的語法并不會(huì)更改。

在 LINQ to Entities 上下文中,F(xiàn)irst 操作符非常有用,尤其是您知道會(huì)從查詢返回單個(gè)記錄時(shí)。例如,您可能有個(gè)查詢,它常在給出 CustomerID 時(shí)獲取一條客戶記錄。這種情況總是返回 0 或 1 條記錄,因此,得到一個(gè)序列不如就得到一個(gè)實(shí)體本身。換句話說,您寧愿獲取 Customer 實(shí)體而非 1 個(gè) Customer 實(shí)體序列。First 方法在某種怦下非常有用,如以下代碼段所示。(由于實(shí)體框架不會(huì)嘗試在客戶端和服務(wù)器之間分發(fā)單個(gè)查詢的執(zhí)行,并且 LINQ to Entities 不支持 Single 方法,因此使用 First 方法是個(gè)輕松的替代方法。)

 
 
  1. using (Entities entities = new Entities())  
  2. {  
  3. var query = (from c in entities.Customers  
  4. where c.CustomerID.Equals("BOLID")  
  5. select c).First();  
  6. Console.WriteLine(query.CompanyName);  

聚合、層次結(jié)構(gòu)和投影

在 LINQ to Entities 查詢中使用聚合操作符(如 Sum)可有助于簡化查詢。例如,以下代碼檢索訂單總額大于 $10,000 的一個(gè)訂單序列:

 
 
  1. using (Entities entities = new Entities())  
  2. {  
  3. var query = from o in entities.Orders  
  4. where o.OrderDetails.Sum(  
  5. od => od.UnitPrice * od.Quantity) >= 10000  
  6. select o;  
  7. foreach (Orders order in query)  
  8. Console.WriteLine(order.OrderID);  

由于 LINQ 可查詢層次結(jié)構(gòu)實(shí)體集合,因此標(biāo)準(zhǔn)查詢操作符也可用于對嵌套實(shí)體序列執(zhí)行運(yùn)算。當(dāng)必須計(jì)算或詢問派生數(shù)據(jù)時(shí),這一點(diǎn)非常有用。派生數(shù)據(jù)可能僅存在于其基本窗體中,如客戶訂單的詳細(xì)信息僅包含單價(jià)和數(shù)量值。在本例中,未在模型中的任何位置提供代表訂單總金額的聚合數(shù)據(jù)。然而,通過在 LINQ 查詢中應(yīng)用 Sum 操作符,仍可檢索消費(fèi)金額超過 $20,000 的所有客戶,如下所示:

 
 
  1. using (Entities entities = new Entities())  
  2. {  
  3. var query = from c in entities.Customers  
  4. where c.Orders.Sum(  
  5. o => o.OrderDetails.Sum(  
  6. od => od.UnitPrice * od.Quantity)) >= 25000  
  7. select c;  
  8. foreach (Customers customer in query)  
  9. Console.WriteLine(customer.CompanyName);  

此示例展示了如何在 LINQ 查詢的多個(gè)層次應(yīng)用標(biāo)準(zhǔn)查詢操作符。查詢最終會(huì)返回一個(gè) Customers 實(shí)體序列,但為達(dá)到此目的,它必須首先深入每個(gè)客戶的訂單以及每個(gè)訂單的訂單詳細(xì)信息獲取所需數(shù)據(jù),這樣才可以計(jì)算每項(xiàng)的價(jià)格,匯總每個(gè)訂單的項(xiàng)目,然后匯總每個(gè)客戶的總額。

Count 操作符是另一聚合標(biāo)準(zhǔn)查詢操作符??赏ㄟ^使用以下代碼確定有多少客戶的消費(fèi)金額超過 $25,000:

 
 
  1. using (Entities entities = new Entities())  
  2. {  
  3. var query = (from c in entities.Customers  
  4. where c.Orders.Sum(  
  5. o => o.OrderDetails.Sum(  
  6. od => od.UnitPrice * od.Quantity)) >= 25000  
  7. select c).Count();  
  8. Console.WriteLine(query);  

可使用 Max 操作符來確定***客戶。以下代碼示例將返回消費(fèi)***的客戶所花費(fèi)的金額。它在層次結(jié)構(gòu)的多個(gè)層級中組合使用 Sum 和 Max 聚合操作符:

 
 
  1. using (Entities entities = new Entities()) 
  2.  {  var query = (from c in entities.Customers  
  3. where c.Orders.Sum(  o => o.OrderDetails.Sum(  od => od.UnitPrice * od.Quantity)) >= 25000  
  4. select c).Count();  Console.WriteLine(query);  }  

投影和排序

您可能還注意到我在之前的示例中暗藏了一個(gè)投影。在使用 Max 操作符之前,LINQ 查詢并不返回客戶列表。而是會(huì)返回一個(gè)投影,此投影創(chuàng)建了包含 CustomerID 屬性和 Total 屬性(客戶的整個(gè)消費(fèi)金額)的一個(gè)新實(shí)體。投影是 LINQ 必不可少的一部分,如前一示例所示,將它們投影到序列中后,就可使用標(biāo)準(zhǔn)查詢操作符來進(jìn)一步處理它們。

顯示了如何創(chuàng)建一個(gè)新實(shí)體投影,其中包含 CustomerID 和客戶的訂單總金額(使用之前討論的 Sum 操作符)。還使用 OrderByDescending 操作符來按計(jì)算總額對投影實(shí)體序列進(jìn)行排序。如果兩個(gè)客戶總額相同,還會(huì)使用另一排序操作符來進(jìn)一步定義順序。例如,還可使用以下代碼修正的 foreach 語句以進(jìn)一步限定排序規(guī)則:

 
 
  1. Figure1Aggregates, Projections, and Ordering  
  2. using (Entities entities = new Entities())  
  3. {  
  4. var query = from c in entities.Customers  
  5. where c.Orders.Sum(  
  6. o => o.OrderDetails.Sum(od => od.UnitPrice)) > 0  
  7. select new  
  8. {  
  9. c.CustomerID,  
  10. Total = c.Orders.Sum(  
  11. o => o.OrderDetails.Sum(od => od.UnitPrice))  
  12. };  
  13. foreach (var item in query.OrderByDescending(x => x.Total))  
  14. Console.WriteLine(item.CustomerID + " == " + item.Total);  
  15. }  
  16. foreach (var item in 
  17. query.OrderByDescending(x => x.Total)  
  18. .ThenBy(x => x.CustomerID))  
  19. {  
  20. Console.WriteLine(item.CustomerID + " == " + item.Total);  

在該代碼段中,我添加了 ThenBy 操作符和一個(gè) Lambda 表達(dá)式,以表示序列應(yīng)首先按 Total 屬性降序排列,然后按投影的 CustomerID 屬性升序排列。

限定符和轉(zhuǎn)換

如果需要確定序列中是否存在某個(gè)值,可使用標(biāo)準(zhǔn)查詢操作符 Any。限定符(如 Any、All 和 Contains)會(huì)搜索元素序列,并評估序列是否滿足 lambda 表達(dá)式的條件。如果需檢查序列以確定某些事宜(例如:是否存在來自特定地址的客戶、所有客戶是否來自同一國家或者任意其他分析確定性問題),它將非常有用。

例如,以下 LINQ 查詢會(huì)檢查是否來自 United Kingdom 的所有客戶都位于 London。它使用限定符 All 并將其傳遞給僅評估城市是否為 London 的 lambda 表達(dá)式。如果序列中的每個(gè)元素都滿足此條件并且 lambda 表達(dá)式返回 true,然后 All 操作符會(huì)返回 true:

 
 
  1. using (Entities entities = new Entities())  
  2. {  
  3. bool allUKCustomerAreFromLondon = (from c in entities.Customers  
  4. where c.Country == "UK" 
  5. select c).All(  
  6. c => c.City.Equals("London"));  
  7. Console.WriteLine(allUKCustomerAreFromLondon ? "Yes" : "No");  

需在此查詢中詢問的另一問題是序列中是否有來自 United Kingdom 的 Cowes 的實(shí)體。對于此問題,可使用 Any 限定符來計(jì)算序列,如下所示:

 
 
  1. using (Entities entities = new Entities())  
  2. {  
  3. bool isOneUKCustomerFromCowes = (from c in entities.Customers  
  4. where c.Country == "UK" 
  5. select c).Any(  
  6. c => c.City.Equals("Cowes"));  
  7. Console.WriteLine(isOneUKCustomerFromCowes? "Yes" : "No");  

Contains 操作符在評估序列中是否包括您所查找的項(xiàng)目時(shí)類似于 Any 操作符。Any 操作符可確定序列的某個(gè)項(xiàng)中是否存在某個(gè)值,而 Contains 操作符則確定序列中是否存在特定項(xiàng)目實(shí)例。例如,在將某個(gè)對象添加到序列中之前,您可能希望確保序列中并未包含該對象。展示了如何檢查。

Figure2Using Contains and Conversion

 
 
  1. using (Entities entities = new Entities())  
  2. {  
  3. Customers customerBSBEV = (from c in entities.Customers  
  4. where c.CustomerID == "BSBEV" 
  5. select c).First();  
  6. var customersUK = from c in entities.Customers  
  7. where c.Country == "UK" 
  8. select c;  
  9. bool isCustomerInSequence = customersUK.Contains(customerBSBEV);  
  10. Console.WriteLine(isCustomerInSequence? "Yes" : "No");  
  11. }  

請注意:首先針對 BSBEV 客戶檢索 Customers 實(shí)體。然后,檢索客戶來自 United Kingdom 的 Customers 實(shí)體序列。***,使用 Contains 操作符來檢查 Customers 序列是否包含 customerBSBEV 變量的實(shí)例。

顯示的 Contains 操作符實(shí)現(xiàn)適用于可基于其實(shí)際實(shí)例信心十足地比較對象的場合。但是,如果需要 Contains 操作符根據(jù)邏輯標(biāo)識進(jìn)行測試又該如何呢?幸運(yùn)的是,Contains 操作符包含一個(gè)重載,可使用它來傳遞實(shí)現(xiàn) IEqualityComparer 接口的對象。要根據(jù) CustomerID 使用 Contains,可按如下所示重新編寫的代碼:

 
 
  1. using (Entities entities = new Entities())  
  2. {  
  3. ...  
  4. bool isCustomerInSequence = customersUK.Contains(customerBSBEV, new CustomerComparer());  
  5. Console.WriteLine(isCustomerInSequence? "Yes" : "No");  

其中 CustomerComparer 定義為

 
 
  1. private class CustomerComparer : IEqualityComparer  
  2. {  
  3. public bool Equals(Customers x, Customers y) {  
  4. if (x == null || y == null)  
  5. return false;  
  6. return x.CustomerID.Equals(y.CustomerID);  
  7. }  
  8. ...  

結(jié)束語

有許多標(biāo)準(zhǔn)查詢操作符均可定義為 Enumerable 和 Queryable 序列類的擴(kuò)展方法。考試大提示如之前所示,這些操作符有助于擴(kuò)展 LINQ 的功能。我還展示了結(jié)合使用多個(gè) .NET Framework 3.5 新增強(qiáng)功能(包括 lambda 表達(dá)式、LINQ、實(shí)體框架和隱式類型化變量)來更加輕松地編寫功能強(qiáng)大的代碼和邏輯。


分享標(biāo)題:詳解LINQ標(biāo)準(zhǔn)查詢操作符
網(wǎng)頁URL:http://m.5511xx.com/article/dhijcjo.html