linq查詢表達(dá)式的基本語法很容易掌握,它使用c#常見的語言構(gòu)造,從外觀上看,和我們常用的sql類似,并且查詢表達(dá)式中的變量可以用匿名類型,所以在很多情況下,不需要指定變量類型就可以構(gòu)建linq表達(dá)式。
linq的數(shù)據(jù)源可以是數(shù)據(jù)庫對象或是xml流等,也可以使實(shí)現(xiàn)了ienumerable或者泛型ienumberable<t>接口的集合對象。
linq的基本語法包含如下的8個上下文關(guān)鍵字,這些關(guān)鍵字和具體的說明如下:
關(guān)鍵字 |
|
from | 指定范圍變量和數(shù)據(jù)源 |
where | 根據(jù)bool表達(dá)式從數(shù)據(jù)源中篩選數(shù)據(jù) |
select | 指定查詢結(jié)果中的元素所具有的類型或表現(xiàn)形式 |
group | 對查詢結(jié)果按照鍵值進(jìn)行分組(igrouping<tkey,telement>) |
into | 提供一個標(biāo)識符,它可以充當(dāng)對join、group或select子句結(jié)果的引用 |
orderby | 對查詢出的元素進(jìn)行排序(ascending/descending) |
join | 按照兩個指定匹配條件來equals連接兩個數(shù)據(jù)源 |
let | 產(chǎn)生一個用于存儲查詢表達(dá)式中的子表達(dá)式查詢結(jié)果的范圍變量 |
下面依此總結(jié)這8個關(guān)鍵字的常用查詢語句寫法。
1.from子句
如果要寫一個linq表達(dá)式,就必須是以from子句開頭。個人覺得from子句中需要注意的地方就是多個from子句的書寫。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
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單個form子句 string [] values = { "linq學(xué)習(xí)" , "linq基本語句" , "from子句" , "單個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多個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子句和多個from子句的書寫,同時(shí)需要理解范圍變量和數(shù)據(jù)源變量這兩個概念。
2.where子句
where子句,它是linq表達(dá)式的元素篩選機(jī)制,除了開始和結(jié)束的位置,它幾乎可以出現(xiàn)在linq表達(dá)式的任意位置上。
在一個linq表達(dá)式中,可以有where子句,也可以沒有;可以有一個,也可以有多個;多個where子句之間的邏輯關(guān)系相當(dāng)于邏輯“與”,每個where子句可以包含1個或多個bool邏輯表達(dá)式,這些條件成為謂詞,謂詞邏輯之間用的是“&&”“||”等而不是sql中的and 、or。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
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.動態(tài)謂詞的篩選 //定義動態(tài)謂詞數(shù)組,在實(shí)際開發(fā)中可以動態(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é)果返回。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
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}; //對查詢結(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子句返回的是一個基于igrouping<tkey,telement>泛型接口的對象序列。
語法和sql的group有點(diǎn)區(qū)別,不注意的話可能會寫錯。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
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子句作為一個臨時(shí)標(biāo)識符,用于group、select、join子句中充當(dāng)其結(jié)果的引用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
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可以按照元素的一個或多個屬性對元素進(jìn)行排序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
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á)式中存儲子表達(dá)式的計(jì)算結(jié)果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
using system; using system.collections.generic; using system.linq; using system.text; namespace linq_let { /// <summary> /// linq let用來存子儲表達(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子句
如果一個數(shù)據(jù)源中元素的某個屬性可以跟另外一個數(shù)據(jù)源的中元素的某個屬性進(jìn)行相等比較,那么這兩個數(shù)據(jù)源可以用join子句進(jìn)行關(guān)聯(lián)。
join子句使用equals關(guān)鍵字進(jìn)行相等比較,而不是常用的雙等號。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
using system; using system.collections.generic; using system.linq; using system.text; namespace linq_join { class program { static void main( string [] args) { //定義兩個數(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 ); //前面的多個from實(shí)現(xiàn)相同的作用:與內(nèi)連接區(qū)別在于:這個中間的操作是叉乘獲得笛卡爾積 var query2=from guest in glist from title in titlelist where guest.name==title.name select new { name = guest.name, src="/uploads/allimg/211115/1435555948-7.jpg" />
延伸 · 閱讀
精彩推薦
|