C#使用LINQ查詢表達(dá)式的基本子句總結(jié)
LINQ查詢表達(dá)式的基本語法很容易掌握,它使用C#常見的語言構(gòu)造,從外觀上看,和我們常用的SQL類似,并且查詢表達(dá)式中的變量可以用匿名類型,所以在很多情況下,不需要指定變量類型就可以構(gòu)建LINQ表達(dá)式。
LINQ的數(shù)據(jù)源可以是數(shù)據(jù)庫對(duì)象或是XML流等,也可以使實(shí)現(xiàn)了IEnumerable或者泛型IEnumberable<T>接口的集合對(duì)象。
LINQ的基本語法包含如下的8個(gè)上下文關(guān)鍵字,這些關(guān)鍵字和具體的說明如下:
關(guān)鍵字 | |
from | 指定范圍變量和數(shù)據(jù)源 |
where | 根據(jù)bool表達(dá)式從數(shù)據(jù)源中篩選數(shù)據(jù) |
select | 指定查詢結(jié)果中的元素所具有的類型或表現(xiàn)形式 |
group | 對(duì)查詢結(jié)果按照鍵值進(jìn)行分組(IGrouping<TKey,TElement>) |
into | 提供一個(gè)標(biāo)識(shí)符,它可以充當(dāng)對(duì)join、group或select子句結(jié)果的引用 |
orderby | 對(duì)查詢出的元素進(jìn)行排序(ascending/descending) |
join | 按照兩個(gè)指定匹配條件來Equals連接兩個(gè)數(shù)據(jù)源 |
let | 產(chǎn)生一個(gè)用于存儲(chǔ)查詢表達(dá)式中的子表達(dá)式查詢結(jié)果的范圍變量 |
下面依此總結(jié)這8個(gè)關(guān)鍵字的常用查詢語句寫法。
1.from子句
如果要寫一個(gè)LINQ表達(dá)式,就必須是以from子句開頭。個(gè)人覺得from子句中需要注意的地方就是多個(gè)from子句的書寫。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace LINQ { /// <summary> /// LINQ,重點(diǎn)是感悟from子句中的查詢變量的靈活 /// </summary> class Program { static void Main(string[] args) { //1單個(gè)form子句 string[] values = { "LINQ學(xué)習(xí)","LINQ基本語句","from子句","單個(gè)from子句"}; var value = from v in values where v.IndexOf("LINQ") > -1 select new { v, v.Length }; foreach (var n in value) { Console.WriteLine("{0},{1}",n.v,n.Length ); } Console.ReadKey(false); //2使用LINQ查詢ArrayList ArrayList gList = new ArrayList(); gList.Add(new GustInfo { Name="DebugLZQ", Age=26, Tel="88888888"}); gList.Add(new GustInfo { Name="博客園",Age=6, Tel ="666666"}); gList.Add(new GustInfo { Name = "M&MSoft", Age =9, Tel = "55555" }); var query = from GustInfo gust in gList where gust.Age > 9 select gust;//范圍變量gust制定了數(shù)據(jù)類型 foreach (GustInfo g in query) { Console.WriteLine("{0} 年齡:{1} 電話:{2}",g.Name,g.Age,g.Tel ); } Console.ReadKey(false); //3復(fù)合from子句 List<GustInfo2> gList2 = new List<GustInfo2>() { new GustInfo2{ Name="DebugLZQ",Age=26,TelTable=new List<string>(){"8888888","138******"}}, new GustInfo2{ Name="博客園",Age=6,TelTable =new List<string>(){"666666","138******"}}, new GustInfo2{ Name="M&MSoft",Age=9,TelTable=new List<string>(){"55555","138******"}} }; //gust、tel都是查詢變量,作用域?yàn)楫?dāng)前查詢語句!??! var query2 = from gust in gList2 from tel in gust.TelTable where tel.IndexOf("5555") > -1 select gust; foreach (var g in query2) { Console.WriteLine("{0} 年齡{1}",g.Name,g.Age ); foreach (var t in g.TelTable) { Console.WriteLine("電話:{0}",t); } } Console.ReadKey(false); //4多個(gè)from子句 var query3 = from GustInfo gust in gList where gust.Age > 6 from GustInfo2 gust2 in gList2 where gust2.Age> 9 select new { gust, gust2 };//查詢結(jié)果定制 foreach (var g in query3) { Console.WriteLine("{0} {1}", g.gust.Name, g.gust2.Name); } Console.ReadKey(false); } } }
程序的運(yùn)行結(jié)果如下:
程序中列舉了from子句的用法示例,注意復(fù)合from子句和多個(gè)from子句的書寫,同時(shí)需要理解范圍變量和數(shù)據(jù)源變量這兩個(gè)概念。
2.where子句
where子句,它是LINQ表達(dá)式的元素篩選機(jī)制,除了開始和結(jié)束的位置,它幾乎可以出現(xiàn)在LINQ表達(dá)式的任意位置上。
在一個(gè)LINQ表達(dá)式中,可以有where子句,也可以沒有;可以有一個(gè),也可以有多個(gè);多個(gè)where子句之間的邏輯關(guān)系相當(dāng)于邏輯“與”,每個(gè)where子句可以包含1個(gè)或多個(gè)bool邏輯表達(dá)式,這些條件成為謂詞,謂詞邏輯之間用的是“&&”“||”等而不是SQL中的and 、or。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LINQ_WHERE { /// <summary> /// LINQ where子句 /// </summary> class Program { static void Main(string[] args) { //1常見的where語句 List<GustInfo> gList = new List<GustInfo>() { new GustInfo(){ Name="DebugLZQ", Age=26,Tel="88888888"}, new GustInfo(){ Name="cnblogs",Age=6,Tel="666666"}, new GustInfo(){ Name="M&MSoft",Age=9,Tel="55555"} }; var query = from gust in gList where (gust.Name.Length > 7 || gust.Name.Substring(0, 1) == "M") && gust.Age > 9 select new { gust.Name, gust.Age }; foreach (var g in query) { Console.WriteLine("{0},{1}", g.Name, g.Age); } Console.ReadKey(false); //2.在where子句中使用自定義函數(shù) var query2 = from GustInfo gust in gList where gust.Name.Length > 5 && Check(gust.Name) select gust; foreach (var g in query2) { Console.WriteLine("{0},{1},{2}", g.Name, g.Age, g.Tel); } Console.ReadKey(false); //3.動(dòng)態(tài)謂詞的篩選 //定義動(dòng)態(tài)謂詞數(shù)組,在實(shí)際開發(fā)中可以動(dòng)態(tài)獲得 string[] names = { "SB","XXX","***","@@@","一些敏感詞"}; var query3 = from GustInfo guest in gList where !names.Contains(guest.Name) select guest; foreach (var q in query3) { Console.WriteLine("{0} 年齡:{1},電話:{2}",q.Name,q.Age,q.Tel ); } Console.ReadKey(false); } //自定義函數(shù) static bool Check(string name) { if (name.Substring(0, 1) == "N") return false; return true; } } }
需要注意一些常用的where子句的寫法。程序的運(yùn)行結(jié)果如下:
3.Select子句
在select子句上可以非常靈活的處理查詢到的元素,然后再把結(jié)果返回。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LINQ_select { /// <summary> /// LINQ select /// 在select子句上,可以非常靈活的處理查詢到的元素,然后再把結(jié)果返回 /// </summary> class MyGustInfo { public string Name { get; set; } public int Age { get; set; } } class Program { static void Main(string[] args) { List<GustInfo> gList = new List<GustInfo>() { new GustInfo(){ Name="DebugLZQ", Age=25, Tel="88888888"}, new GustInfo(){ Name="cnblogs", Age=6, Tel="666666"}, new GustInfo(){ Name="M&M", Age=9, Tel="55555"} }; var query = from gust in gList where gust.Age >= 9 && gust.Age <= 30 select gust.Name.Replace("&", "mm");//select子句靈活應(yīng)用 var query2 = from gust in gList where gust.Age >= 9 && gust.Age <= 30 select MyProc(gust.Name); var query3 = from gust in gList where gust.Age >= 9 && gust.Age <= 30 select new { gust.Name,gust.Age}; var query4 = from gust in gList where gust.Age >= 9 && gust.Age <= 30 select new MyGustInfo { Name=gust.Name+"My", Age=gust.Age+1};//對(duì)查詢結(jié)果進(jìn)行投影 foreach (var v in query) { Console.WriteLine(v); } foreach (var v in query2) { Console.WriteLine(v); } foreach (var v in query3) { Console.WriteLine(v.Name+v.Age ); } foreach (var v in query4) { Console.WriteLine(v.Name+v.Age ); } Console.ReadKey(false); } static string MyProc(string s) { return s + "Better"; } } }
程序的運(yùn)行結(jié)果如下:
4.group子句
根據(jù)語法的規(guī)定,LINQ表達(dá)式必須以from子句開頭,以select或group子句結(jié)束,所以除了使用select來返回結(jié)果外,也可以使用group子句來返回元素分組后的結(jié)果。
group子句返回的是一個(gè)基于IGrouping<TKey,TElement>泛型接口的對(duì)象序列。
語法和SQL的group有點(diǎn)區(qū)別,不注意的話可能會(huì)寫錯(cuò)。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LINQ_group { /// <summary> /// LINQ group子句 /// </summary> class Program { static void Main(string[] args) { List<GustInfo> gList = new List<GustInfo>() { new GustInfo(){ Name="DebugLZQ",Age=26,Tel="187********"}, new GustInfo(){ Name="Sarah",Age=25,Tel="159********"}, new GustInfo(){ Name="Jerry",Age=35,Tel="135********"}, new GustInfo(){ Name="M&M",Age=16,Tel="136********"}, new GustInfo(){ Name="DebugMan",Age=26,Tel="136********"}, new GustInfo(){ Name="Jerry&Tom",Age=19,Tel="136********"}, }; var query = from guest in gList group guest by guest.Name.Substring(0, 1);//分組鍵key是string類型 //遍歷鍵值和鍵值所屬元素 foreach (IGrouping<string, GustInfo> guestGroup in query) { Console.WriteLine("分組鍵:{0}",guestGroup.Key ); foreach (var g in guestGroup) { Console.WriteLine("{0} 年齡:{1} 電話:{2}",g.Name,g.Age,g.Tel ); } } Console.ReadKey(false); Console.WriteLine("-----------------------------------"); var query2 = from guest in gList group guest by guest.Age > 20;//分組鍵key是bool類型表達(dá)式的結(jié)果 foreach (IGrouping<bool, GustInfo> guestGroup in query2) { Console.WriteLine("年齡是否大于20 分組鍵:{0}", guestGroup.Key); foreach (var g in guestGroup) { Console.WriteLine("{0} 年齡:{1} 電話:{2}", g.Name, g.Age, g.Tel); } } Console.ReadKey(false); } } }
程序的運(yùn)行結(jié)果如下:
5.into子句
into子句作為一個(gè)臨時(shí)標(biāo)識(shí)符,用于group、select、join子句中充當(dāng)其結(jié)果的引用。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LINQ_into { /// <summary> /// LINQ group /// </summary> class Program { static void Main(string[] args) { List<GustInfo> gList = new List<GustInfo>() { new GustInfo(){ Name="DebugLZQ",Age=26,Tel="187********"}, new GustInfo(){ Name="Sarah",Age=25,Tel="159********"}, new GustInfo(){ Name="Jerry",Age=35,Tel="135********"}, new GustInfo(){ Name="M&M",Age=16,Tel="136********"}, new GustInfo(){ Name="DebugMan",Age=26,Tel="136********"}, new GustInfo(){ Name="Jerry&Tom",Age=19,Tel="136********"}, }; //1.into用于group子句 var query = from guest in gList group guest by guest.Name.Substring(0, 1) into grguest orderby grguest.Key descending select grguest; var query2 = from guest in gList group guest by guest.Name.Substring(0, 1) into grguest orderby grguest.Key ascending select grguest; //2.select 子句中的into子句 var query3 = from guest in gList select new { NewName = guest.Name, NewAge = guest.Age } into newguest orderby newguest.NewAge select newguest; foreach (var guestGroup in query) { Console.WriteLine("分組鍵:{0}",guestGroup.Key ); foreach (var g in guestGroup) { Console.WriteLine("{0} 電話:{1}",g.Name,g.Tel ); } } Console.ReadKey(false); foreach (var newg in query3) { Console.WriteLine("{0} 年齡:{1}",newg.NewName,newg.NewAge ); } Console.ReadKey(false); } } }
程序運(yùn)行結(jié)果如下:
6.orderby子句、thenby子句
LINQ可以按照元素的一個(gè)或多個(gè)屬性對(duì)元素進(jìn)行排序。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LINQ_orderby { class Program { /// <summary> /// LINQ orderby (ascending descending) /// </summary> /// <param name="args"></param> static void Main(string[] args) { List<GustInfo> gList = new List<GustInfo>() { new GustInfo(){ Name="DebugLZQ",Age=26,Tel="187********"}, new GustInfo(){ Name="Sarah",Age=25,Tel="159********"}, new GustInfo(){ Name="Jerry",Age=35,Tel="135********"}, new GustInfo(){ Name="M&M",Age=16,Tel="136********"}, new GustInfo(){ Name="DebugMan",Age=26,Tel="136********"}, new GustInfo(){ Name="Jerry&Tom",Age=19,Tel="136********"}, }; //按照年齡排序 var query = from guest in gList orderby guest.Age select guest; var query1 = from guest in gList orderby guest.Age ascending select guest; var query2 = from guest in gList orderby guest.Age descending select guest; //按照年齡進(jìn)行排序,按照名字字?jǐn)?shù)進(jìn)行次要排序 var query3 = from guest in gList orderby guest.Age, guest.Name.Length select guest; var query4 = from guest in gList orderby guest.Age descending , guest.Name.Length ascending select guest; var query5 = from guest in gList orderby guest.Age, guest.Name.Length,guest.Tel select guest; foreach (var guest in query2) { Console.WriteLine("{0} 年齡:{1} 電話:{2}",guest.Name,guest.Age,guest.Tel ); } Console.ReadKey(false); foreach (var guest in query4) { Console.WriteLine("{0} 年齡:{1} 電話:{2}", guest.Name, guest.Age, guest.Tel); } Console.ReadKey(false); } } }
程序運(yùn)行結(jié)果如下:
7.let子句
let子句用于在LINQ表達(dá)式中存儲(chǔ)子表達(dá)式的計(jì)算結(jié)果。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LINQ_let { /// <summary> /// LINQ let用來存子儲(chǔ)表達(dá)式的計(jì)算結(jié)果 /// </summary> class Program { static void Main(string[] args) { List<GustInfo> gList = new List<GustInfo>() { new GustInfo(){ Name="DebugLZQ",Age=26,Tel="187********"}, new GustInfo(){ Name="Sarah",Age=25,Tel="159********"}, new GustInfo(){ Name="Jerry",Age=35,Tel="135********"}, new GustInfo(){ Name="M&M",Age=16,Tel="136********"}, new GustInfo(){ Name="DebugMan",Age=26,Tel="136********"}, new GustInfo(){ Name="Jerry&Tom",Age=19,Tel="136********"}, }; //使用let子句創(chuàng)建范圍變量g,并通過g構(gòu)建查詢表達(dá)式 var query = from guest in gList let g = guest.Name.Substring(0, 1) where g == "D" || g == "J" select guest; //也可以不使用let,上面的語句等效于下 var query2 = from guest in gList where guest.Name.Substring(0, 1) == "D" || guest.Name.Substring(0, 1) == "J" select guest; foreach (var g in query) { Console.WriteLine("{0} 年齡:{1} 電話:{2}",g.Name,g.Age,g.Tel ); } Console.ReadKey(false); Console.WriteLine("不使用let,等效的語句結(jié)果"); foreach (var g in query2) { Console.WriteLine("{0} 年齡:{1} 電話:{2}", g.Name, g.Age, g.Tel); } Console.ReadKey(false); } } }
程序的運(yùn)行結(jié)果如下:
8.join子句
如果一個(gè)數(shù)據(jù)源中元素的某個(gè)屬性可以跟另外一個(gè)數(shù)據(jù)源的中元素的某個(gè)屬性進(jìn)行相等比較,那么這兩個(gè)數(shù)據(jù)源可以用join子句進(jìn)行關(guān)聯(lián)。
join子句使用equals關(guān)鍵字進(jìn)行相等比較,而不是常用的雙等號(hào)。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LINQ_join { class Program { static void Main(string[] args) { //定義兩個(gè)數(shù)據(jù)源 List<GustInfo> gList = new List<GustInfo>() { new GustInfo(){ Name="DebugLZQ",Age=26,Tel="187********"}, new GustInfo(){ Name="Sarah",Age=25,Tel="159********"}, new GustInfo(){ Name="Jerry",Age=35,Tel="135********"}, new GustInfo(){ Name="M&M",Age=16,Tel="136********"}, new GustInfo(){ Name="DebugMan",Age=26,Tel="136********"}, new GustInfo(){ Name="Jerry&Tom",Age=19,Tel="136********"}, }; List<GuestTitle> titleList = new List<GuestTitle>() { new GuestTitle(){Name="DebugLZQ",Title="Soft Engineer"}, new GuestTitle(){Name="DebugLZQ",Title="Team Leader"}, new GuestTitle(){Name="Sarah",Title="Test Engineer"}, new GuestTitle(){Name="Jerry",Title="Head Master"} }; //1.根據(jù)姓名進(jìn)行內(nèi)連接 var query = from guest in gList join title in titleList on guest.Name equals title.Name select new { Name=guest.Name ,Title=title.Title,Age=guest.Age }; foreach (var g in query) { Console.WriteLine("{0} {1} 年齡:{2}",g.Name,g.Title ,g.Age ); } Console.ReadKey(false); //前面的多個(gè)from實(shí)現(xiàn)相同的作用:與內(nèi)連接區(qū)別在于:這個(gè)中間的操作是叉乘獲得笛卡爾積 var query2=from guest in gList from title in titleList where guest.Name==title.Name select new { Name = guest.Name, Title = title.Title, Age = guest.Age }; foreach (var g in query2) { Console.WriteLine("{0} {1} 年齡:{2}", g.Name, g.Title, g.Age); } Console.ReadKey(false); //2.根據(jù)姓名進(jìn)行分組連接 //根據(jù)名字分組后,得到每個(gè)名字下的全部名稱 var query3 = from guest in gList join title in titleList on guest.Name equals title.Name into tgroup select new { Name=guest.Name,Titles=tgroup }; foreach (var g in query3) { Console.WriteLine(g.Name); foreach (var g2 in g.Titles) { Console.WriteLine(" {0}",g2.Title ); } } Console.ReadKey(false); //3.根據(jù)姓名進(jìn)行左外連接 //無職務(wù)的輸出為空缺 var query4 = from guest in gList join title in titleList on guest.Name equals title.Name into tgroup from subtitle in tgroup.DefaultIfEmpty() select new { Name=guest.Name,Title=subtitle==null?"空缺":subtitle.Title }; foreach (var g in query4) { Console.WriteLine("{0} {1} ",g.Name ,g.Title ); } Console.ReadKey(false); } } }
程序結(jié)果如下:
以上就是LINQ的基本子句的常用用法,文字不是很多,因?yàn)榇a中都有詳細(xì)的注釋說明。
- C#集合查詢Linq在項(xiàng)目中使用詳解
- C# Linq延遲查詢的執(zhí)行實(shí)例代碼
- c# Linq查詢?cè)斀?/a>
- c# 動(dòng)態(tài)構(gòu)建LINQ查詢表達(dá)式
- C# linq查詢之動(dòng)態(tài)OrderBy用法實(shí)例
- C#中Linq延遲查詢的例子
- C#使用linq語句查詢數(shù)組中以特定字符開頭元素的方法
- C#使用linq查詢大數(shù)據(jù)集的方法
- C#中Linq查詢基本操作使用實(shí)例
- C# LINQ查詢表達(dá)式及對(duì)應(yīng)LAMBDA表達(dá)式的用法
- C#使用LINQ查詢操作符實(shí)例代碼(一)
相關(guān)文章
基于C# 寫一個(gè) Redis 數(shù)據(jù)同步小工具
Redis支持主從同步。數(shù)據(jù)可以從主服務(wù)器向任意數(shù)量的從服務(wù)器上同步,從服務(wù)器可以是關(guān)聯(lián)其他從服務(wù)器的主服務(wù)器。這篇文章主要介紹了用 C# 寫一個(gè) Redis 數(shù)據(jù)同步小工具,需要的朋友可以參考下2020-02-02WPF實(shí)現(xiàn)Interaction框架的Behavior擴(kuò)展
這篇文章介紹了WPF實(shí)現(xiàn)Interaction框架Behavior擴(kuò)展的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06C#實(shí)現(xiàn)對(duì)象XML序列化的方法
這篇文章主要介紹了C#實(shí)現(xiàn)對(duì)象XML序列化的方法,是C#常見的實(shí)用技巧,需要的朋友可以參考下2014-11-11C#實(shí)現(xiàn)將javascript文件編譯成dll文件的方法
這篇文章主要介紹了C#實(shí)現(xiàn)將javascript文件編譯成dll文件的方法,涉及C#編譯生成dll動(dòng)態(tài)鏈接庫文件的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11詳解C#中多態(tài)性學(xué)習(xí)/虛方法/抽象方法和接口的用法
這篇文章主要為大家詳細(xì)介紹了C#中多態(tài)性學(xué)習(xí)、虛方法、抽象方法和接口的用法的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-03-03C#實(shí)現(xiàn)漂亮的數(shù)字時(shí)鐘效果
這篇文章主要介紹了C#實(shí)現(xiàn)漂亮的數(shù)字時(shí)鐘效果,涉及時(shí)間函數(shù)的應(yīng)用及繪圖的方法,需要的朋友可以參考下2014-10-10C#使用base64對(duì)字符串進(jìn)行編碼和解碼的測(cè)試
今天小編就為大家分享一篇關(guān)于C#使用base64對(duì)字符串進(jìn)行編碼和解碼的測(cè)試,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02