通過上一章節的學習,相信大家已經掌握了學習LINQ的前期的准備知識。在這一節里,我會通過一些列的實例向大家講解LINQ的語法。
在開始介紹之前,先把上節最后的一個小例子給溫習下。后邊的所講的都圍繞這個例子展開:
先創建一個Person類,作為數據實體
public class Person
{
public string Name
{
get;
set;
}
public string Sex
{
get;
set;
}
public int Age
{
get;
set;
}
}
List<Person> list=new List<Person>()
{
new Person(){ Name="Olive",Sex="女",Age=22},
new Person(){ Name="Moyao",Sex="男",Age=23},
new Person(){ Name="Momo",Sex="女",Age=22},
new Person(){ Name="Only",Sex="女",Age=20},
new Person(){ Name="Love",Sex="女",Age=21},
new Person(){ Name="For",Sex="女",Age=22},
new Person(){ Name="Remote",Sex="男",Age=23},
new Person(){ Name="Snow",Sex="女",Age=23}
};
/從list集合中選出性別為“女”的人
var girls = from g in list
where g.Sex== "女"
select g;
//從list集合中選出性別為“男”的人
var boys = list.Where(p => p.Sex == "男");
Console.WriteLine("Girls");
foreach (var g in girls)
{
Console.WriteLine("姓名:" + g.Name + "--性別:" + g.Sex + "--年齡:" + g.Age);
}
Console.WriteLine("Boys");
foreach (var b in boys)
{
Console.WriteLine("姓名:" + b.Name + "--性別:" + b.Sex + "--年齡:" + b.Age);
}
輸出結果如下:

細心的朋友們可能會發現從list集合中獲取信息的方式不一樣,在獲取性別為“女”的集合中采用的是 from g in list where g.Sex== "女" select g;
而在獲取性別為“男”的集合中采用的為 list.Where(p => p.Sex == "男");
或許會有人問,這兩種查詢方式有什么區別呢?上面的第一種方法叫查詢語法(query syntax),看上去和SQL的語句很相似。查詢語法使用查詢表達式書寫。第二種方法叫方法語法(method syntax)是命令形式,它使用的是標准的方法調用,方法是一組叫做標准查詢運算符的方法。雖然形式上這兩種查詢方法不同,事實上這兩種方法存在着緊密的聯系,在CLR內只識別查詢方法,因此在每次查詢的時候編譯器在編譯時會將查詢語句翻譯為查詢方法,當然大部分的查詢方法也都有對應的查詢語句形式,例如:where對應 Where(),select對應Select(),orderby 對應orderby(),group對應group(),join 對應Join(),distinct對應Distinct(),union對應Union(),Intersect對應Intersect(),except對應Except(),等等。
我們看SQL查詢形式:select 查詢內容 from 數據源 where 查詢條件,也就是分為數據源、查詢條件、查詢內容這三部分,在LINQ查詢里也是分這三部分,從上面的例子中我們可以知道它的查詢方式是這樣的 from a(查詢內容) in 數據源 where 查詢條件 select a(查詢內容)
下邊就從最基本的介紹開始。
1、from
在SQL里邊from后跟的是數據源,當然在LINQ里from子句指定的也是要作為數據源使用的數據集合,但是它引入了迭代變量,迭代變量有序表示數據源的每一個元素,最后查詢返回的是一個迭代變變量的集合。
2、Where/where()
在SQL里where后跟的是查詢條件,在LINQ里也是一樣的。
請看示例:
//查詢年齡大於21且性別為女的人員的個人信息
var girls1 = from g in list
where g.Age > 21 && g.Sex == "女"
select g;
//使用查詢方法查詢
// var girls1 = list.Where(g => g.Age > 21 && g.Sex == "女");
Console.WriteLine("年齡大於21且性別為女的個人信息:");
foreach (var g in girls1)
{
Console.WriteLine("姓名:" + g.Name + "--性別:" + g.Sex + "--年齡:" + g.Age);
}
實驗結果:

從實驗結果中我們可以看到,在查詢語句中where后邊也可以跟一個或多個查詢條件,去篩選數據,以得到想要的結果,或許還有人對使用查詢方法有點疑問,查詢方法where()里邊的參數到底是什么呢?這里就用到了上一節我們講的Lambda表達式。
請看Where()的原型:
where() 語法是:
public static IEnumerable<TSource> where<TSource>(
this IEnumerable<TSource> source,
Func<TSource,bool> predicate)
由上一節學的知識我們可以知道該方法是一個泛型的擴展方法,該方法只接受一個Func<TSource,bool>泛型委托參數,這里的predicate是一個判斷條件。
我們上邊用的list.Where(g=>g.Age>21 && g.Sex) 高亮部分就相當於一個委托參數,所以用where()查詢方法才能查出符合條件的信息。至於上邊提到的Selec()、Orderby()等查詢方法語法原型都是泛型的擴展方法和where()差不多,后邊就不再過多的介紹其方法原型了。
3、select/select()
select 篩選出符合條件的數據
用查詢語句查詢var g1=from g in list where g.Name="Olive" select g1;
用查詢方法查詢姓名為Olive的人員信息:
var g1 = list.Select(p=>p).Where(p=>p.Name == "Olive");
結果如下:

4、排序:orderby/OrderBy()、thenBy() 、ThenByDescending()
用orderby進行排序(默認升序)
Var ps=from p in list orderby p.Age select p
用OrderBy()進行排序(升序)
var g11 = list.OrderBy(p => p.Age);
結果如圖:

用orderby descending降序排列
Var ps=from p in list select p orderby p.Age descending
用OrderByDescending()降序排序
var g11 = list.OrderByDescending(p => p.Age);
結果如圖:

用ThenBy()做二次排序,先按年齡的升序排序,如果年齡相等的就再按姓名升序排序
var g12 = list.OrderBy(p => p.Age).ThenBy(p => p.Name);
結果如圖:

用ThenByDescending()做二次排序,先按年齡的升序排序,如果年齡相等的就再按姓名降序排序
var g12 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name);
結果如圖:

5、group/GroupBy()
使用group子句可產生按照指定的鍵組織的組序列。
用group子句進行分組
Var ps=from p in list group p.Sex into p select p;
使用GroupBy()進行分組
var g11 = list.OrderByDescending(p => p.Age).GroupBy(p=>p.Sex);
結果如下:

6、Take、TakeWhile、Skip、SkipWhile
6.1、Take:用於從輸入序列中返回指定數量的元素
//從滿足條件的的序列中返回3條信息
var g12 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Take(3);

6.2、TakeWhile:只要滿足一定條件的就會馬上返回序列元素
var g12 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).TakeWhile(p=>p.Sex=="女");
結果如圖:

6.3 、Skip:用於從輸入序列中跳過指定個數的元素,返回由序列中剩余的元素所組成的 新序列
//跳過4個指定元素,然后將剩余的元素組成新序列返回
var g12 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Skip(4);
6.4、SkipWhile:用於從輸入序列中跳過滿足一定條件指定數量的元素,返回由序列中剩余的元素所組成的新序列
//跳過姓名為“Olive”的信息,然后將剩余的的元素組成新的序列返回
var g12 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).SkipWhile(p=>p.Name=="Olive");
結果如下:

7、Count(),Max()/Min(),Average(),Sum()聚合方法
7.1、Count():統計序列中元素個數
示例:var g121 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Count();
Console.WriteLine("總共有{0}條信息!"+g121);
結果:

7.2、Max()/Min()求最大/最小值
示例:求最大年齡:
var g121 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Max(p => p.Age);
Console.WriteLine("最大年齡為:"+g121);
結果:

示例:求最小年齡:
var g121 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Min(p => p.Age);
Console.WriteLine("最小年齡為:"+g121);
結果:

7.3、Average()求平均值
示例:求平均年齡:
var g121 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Average(p => p.Age);
Console.WriteLine("平均年齡為:"+g121);
結果:

7.4、Sum()累加求和
示例:累加年齡:
var g121 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Average(p => p.Age);
Console.WriteLine("累加年齡為:"+g121);
結果:

8、Join(),GroupJoin(),Union(),Intersect(),Except(),Contact(),Distinct操作符
8.1、Join()用於連接兩個序列,和SQL里的Join語句連接多表一樣,連接操作接受兩個集合然后創建一個臨時的對象集合,每個對象包含原始集合對象中的所有字段,使用連接來結合兩個或更多個集合中的數據。
例如:這里使用上邊新建的Person類,然后在新建一個Profession(職業)類
Public class Profession
{
Public string Name{get;set:}
Public string Zhiye{get;set;}
}
List<Person> list=new List<Person>()
{
new Person(){ Name="Olive",Sex="女",Age=22},
new Person(){ Name="Moyao",Sex="男",Age=23},
new Person(){ Name="Momo",Sex="女",Age=22},
new Person(){ Name="Only",Sex="女",Age=20},
new Person(){ Name="Love",Sex="女",Age=21},
new Person(){ Name="For",Sex="女",Age=22},
new Person(){ Name="Remote",Sex="男",Age=23},
new Person(){ Name="Snow",Sex="女",Age=23}
};
List<Profession> listprofession = new List<Profession>
{
new Profession() { Name = "Olive", ZhiYe = "會計" },
new Profession() { Name = "Remote", ZhiYe = "IT Coder" },
new Profession() { Name = "BLove", ZhiYe = "學生" },
new Profession(){ Name="AFor",ZhiYe="作家"}
};
使用Join查詢語句查詢,從Person序列和Profession序列里查詢出姓名相同的信息,組合成一個新的序列,並顯示姓名和職業
var showzhiye = from p in list
join pf in listprofession on p.Name equals pf.Name
select new
{
Name = p.Name,
ZhiYe = pf.ZhiYe
};
foreach (var p in showzhiye)
{
Console.WriteLine("姓名:" + p.Name + " 職業:" + p.ZhiYe);
}
使用Json()方法查詢:
var showzhiye = list.Join(listprofession, p => p.Name, pf => pf.Name, (p, pf) => new
{
Name = p.Name,
ZhiYe = pf.ZhiYe
});
兩種方法查詢的結果一樣如下:

8.2、GroupJoin():將基於鍵相等對兩個序列的元素進行關聯並對結果進行分組。使用默認的相等比較器對鍵進行比較。
//var showzhiye = list.GroupJoin(listprofession, p => p.Name, pf => pf.Name, (p, pf) => new
{ Name = p.Name, ZhiYe = pf.Max(pf1=>pf1.Name)});
var showzhiye = listprofession.GroupJoin(list, pf => pf.Name, p => p.Name, (pf, p) => new
{
Name = pf.Name,
ZhiYe =pf.ZhiYe,
Count=p.Count()
});
結果:

8.3、Union():用於將兩個輸入序列中的元素合並成一個新的序列,且新序列中自動去除重復的序列
示例: List<Person> list1 = new List<Person>()
{
new Person(){ Name="Olive",Sex="女",Age=18},
new Person(){ Name="Moyao",Sex="男",Age=19},
new Person(){ Name="Momo",Sex="女",Age=20},
new Person(){ Name="Olive116",Sex="女",Age=18},
new Person(){ Name="Moyao116",Sex="男",Age=19},
new Person(){ Name="Momo116",Sex="女",Age=20},
};
var uniontest = list.Union(list1);//將list1和上邊所示的list合並,自動去除重復列
foreach (var p in uniontest)
{
Console.WriteLine("姓名:" + p.Name + " 年齡:"+p.Age +" 性別:"+p.Sex );
}
結果:

8.4、Intersect():求兩個序列的交集,將兩個序列中相同的元素挑選出來組成一個新的序列
這里還是用8.3里的數據源list1、list
示例: var intersectTest = list1.Intersect(list);
foreach (var p in intersectTest)
{
Console.WriteLine("姓名:" + p.Name + " 年齡:"+p.Age +" 性別:"+p.Sex );
}
結果:

8.5、Except(),現有A、B兩序列,返回僅在A序列中的元素所組成的序列,相當於求差集
var ExceptTest = list.Except(list1);
8.6、Contact():聯接兩個序列
示例: var ExceptTest = list.Concat(list1);
foreach (var p in ExceptTest)
{
Console.WriteLine("姓名:" + p.Name + " 年齡:"+p.Age +" 性別:"+p.Sex );
}
結果:

8.7、Distinct():檢測每一個輸入元素是否有相同的,如果有相同的元素則作為一個元素添加到結果序列中,相當於去除重復;
示例:list.Distinct();
本來想在這一節把所有的LINQ語法給全部講完的,才發現這一節已經講了很多了,這一節就講到這里吧,給大家一個吸收消化的時間,在下一節里我會把剩下的LINQ語法給全部講完。希望能給大家帶來一些幫助。也請大家多多指教。
