语法说明:
以 from 开头,后接开发人员自定义的命名,代表集合中的元素
in后面的数据源(source data)必须是IEnumerable
必须以select(
var excellent = from s in students
//where s.Majors.Count > 2
//where s.Majors.Contains(csharp)
//where !s.Majors.Contains(Javascript)
where s.Name.StartsWith('王') && s.Score > 80
select s;
var excellent = from s in students
//orderby s.Score 默认升序(ascending)
orderby s.Score descending
select s;
还可以先按某字段升/降序,再按另一字段升降序(同ThenBy())
var excellent = from s in students
orderby s.Score ascending, s.Name descending
select s;
orderby和where可以组合使用:
var excellent = from s in students
where s.Score > 80
orderby s.Score ascending, s.Name descending
select s;
var result = from m in majors
group m by new { m.Teacher, m.Age } //使用匿名对象
还可以对分组结果集再运算(统计)
var result = from m in majors
group m by m.Teacher
into gm //into类似于命名,将之前的结果集命名为:gm
select new //利用投影
gm.Key, //老师的名字
Count = gm.Count() //聚合运算
此外,多个字段组成的连接条件,使用匿名类(调整数据源,设定两个不同年龄的飞哥):
on new { Name = m.Teacher, m.Age } equals new { t.Name, t.Age }
结果还可以投影:
select new
MajorName = m.Name,
TeacherName = t.Name,
t.Age
还可以继续join,关联多个集合:
var result = from m in majors
join t in teachers
on new { Name = m.Teacher, m.Age } equals new { t.Name, t.Age }
join s in students
on m.Name equals s.Name
还可以在结果中过滤
where t.Name == "小鱼"
outer join
其实上面(默认)的join,又被称之为inner join,其特点是只会返回完全满足join条件的集合元素。
与之相对的,还有(left)outer join,即:所有左边的(第一个)集合元素都必须返回,哪怕在右边的(第二个)集合无法匹配到(无法匹配就显示为null)。
为了演示效果,添加一个CSS的Major:
Major Css = new Major { Name = "CSS" };
不要忘了将其添加到集合:
IEnumerable<Major> majors = new List<Major> { csharp, SQL, Javascript, UI, Css };
PS:Linq中只有left join,没有right join
在Linq中需要使用DefaultIfEmpty()方法实现outer join的效果:
var result = from m in majors //major放在前面,表示所有的major都要呈现
join t in teachers
on m.Teacher equals t.Name
into mt //又见into,mt代表的是teachers
//调用了DefaultIfEmpty()并再次from
from joined in mt.DefaultIfEmpty()
select new
MajorName = m.Name,
TeacherName = joined?.Name ?? "没有老师",
TeacherAge = joined?.Age ?? 0
复习:null值的处理
#试一试#:如果我们想要(以teachers为基准)返回所有的teacher元素,应该如何join?
cross join
左右两边的集合进行无条件的多对多交叉连接(执行笛卡尔乘积),使用多个from实现
var result = from t in teachers
from m in majors
select new { t, m };
实际上,inner join和outer join都是在cross join的基础上进行过滤,比如我们加这么一个条件:
where t.Name == m.Teacher
结果就变成了inner join。(另:无论何种join,都是可以join之后继续where过滤的)
var result = from s in students
let ms = s.Majors //把所有的 Major 先暴露出来
from m in ms //后面就可以使用 let 指定的 ms
select new { student = s.Name, major = m.Name };
一样添加where条件
where m.Name.ToLower().Contains("s")
var result = from s in students.Where(x => x.Score > 80)
result = result.OrderByDescending(r => r.student.Score);
注意:不要忘记使用返回值赋值!