本篇逐一介绍linq各个关键字的用法(from,select,group,into等),本篇所有的案例都是用linqpad来完成的(官方地址:http://www.linqpad.net/),建议想学好linq的博友们下载这个工具。
From
查询表达式是以from开头的(之所以不延用sql的语法以'select'开头,是为了配合vs的智能语法提示)。
单个from
代码
var query = from a in new string[]{"a","b","c"} select a; foreach(var item in query){ Console.WriteLine(item); }
结果
多个from子句执行联接
多个from时,会对两个数据源做笛卡尔积,简单一点说,有A和B两个表,分别有x和y条记录,A和B的笛卡尔积会求出x*y条记录,即每一个A表里的一条记录对应了B表里的y条记录。可实现join语法相同的操作。
示例一:
代码
var query = from a in new string[]{"a","b","c"} from b in new int[]{1,2,3} select new{A=a,B=b}; foreach(var item in query){ Console.WriteLine(item.A+" "+item.B); }
结果
当然,可以再对上面的笛卡尔积做where的条件筛选操作,这样就会求出自己想要的记录。
复合from子句
上一个示例只是简单的多个from的联接,如果下一个from子句的数据源和上一个from对象有联系时,就要用到复合from子句,但语法是一样的
代码
from a in new List<(string name,string[] scores)>{ {("张三",new string[]{"80","90"})}, {("李四",new string[]{"30","40"})} } from b in a.scores select new {a,b}
结果的结构
where
where
子句用在查询表达式中,用于指定将在查询表达式中返回数据源中的哪些元素。 它将一个布尔条件(谓词)应用于每个源元素(由范围变量引用),并返回满足指定条件的元素。 一个查询表达式可以包含多个 where
子句,一个子句可以包含多个谓词子表达式
如下面的两个查询表达式是一样的
from a in new int[]{1,2,3,4,5} where a>1 && a<4 select a from a in new int[]{1,2,3,4,5} where a>1 where a<4 select a
select
select用于生成要返回的结果,可做为查询表达式的结尾(必须以select或是group结尾)。
返回结果为旧类型
可参考from一节里的“单个from”案例,select语法没有new关键字,以之前的类型为返回
返回结果为新类型
可参考from一节里的“多个from”案例,select语法后跟了new关键字,会以new的匿名类型做为新的返回类型。下面将代码稍做改动,变于查看每个结果记录的结构。
代码:
var query = from a in new string[]{"a","b","c"} from b in new int[]{1,2,3} select new{FieldOfA=a,FieldOfB=b}; foreach(var item in query){ //Console.WriteLine(item.A+" "+item.B); Console.WriteLine(item); }
结果
排序
有升序:orderby,thenby
降序:OrderByDescending,ThenByDescending
var list=new List<string[]>{ new string[3]{"学校1","1年级","班级1"}, new string[3]{"学校1","1年级","班级2"}, new string[3]{"学校1","2年级","班级1"}, new string[3]{"学校1","2年级","班级2"}, new string[3]{"学校2","1年级","班级1"}, new string[3]{"学校2","1年级","班级2"}, new string[3]{"学校2","2年级","班级1"}, new string[3]{"学校2","2年级","班级2"} }; var query1=list.OrderBy(a=>a[0]).ThenByDescending(a=>a[1]).ThenBy(a=>a[2]).Select(a=>a); var query2 = from a in list orderby a[0],a[1] descending,a[2] select a; foreach(var item in query1){ Console.WriteLine($"{item[0]}--{item[1]}--{item[2]}"); } foreach(var item in query2){ Console.WriteLine($"{item[0]}--{item[1]}--{item[2]}"); }
的查询表达式里只有orderby,配合descending来使用。
group
1))语法上:可以以group作为查询表达式的结尾(如from a in tab_a group a by a.xxx),但如果group后跟了into,必须继续编写该查询,并最终使用一个select
语句或另一个 group
子句结束该查询
2)返回的类型:返回一个 IGrouping<TKey,TElement> 对象序列,TKey的类型为by关键字后面的类型,TElement的类型为group关键字后面的类型
3)分组键的类型:组键可以是任何类型,如字符串、内置数值类型、用户定义的命名类型或匿名类型。分组键即by关键字后的对象
以单个键为分组键
示例
from a in new List<string>{"aa","aa","ab","ab","ba","ba","bb","bb"} group a by a[0]
以组合键为分组键
示例
from a in new List<string>{"aa1","aa2","ab1","ab2"} group a by new{first=a[0],second=a[1]}
以布尔值为分组键
示例
from a in new List<string>{"a","ab","abc","abcd"} group a by a.Length>2
返回类型里的元素类型
group返回的类型为 IGrouping<TKey,TElement>,TKey的类型由by关键字后面的类型决定;而TElement的类型则于group关键字后面的类型决定。
示例1
from a in new List<string>{"aa1","aa2","ab1","ab2"} group new{firstChar=a[0],secondChar=a[1],thirdChar=a[2] } by new{first=a[0],second=a[1]}
示例二
from a in new List<string>{"张三","李四"} join b in new List<string[]>{ new string[]{"张三","英语","60"}, new string[]{"张三","语文","70"}, new string[]{"李四","英语","90"}, new string[]{"李四","语文","80"}, } on a equals b[0] group new {姓名=a,学科=b[1],成绩=b[2]} by a