除了可以用我们之前学习的Linq方法,还可以使用Linq查询表达式:
var excellent = from s in students select s;这是一种类似于(数据库查询语言)SQL的写法。推出这种书写方法,应该是为了照顾SQL开发人员,或者暗示/表明Linq是可以“代替”SQL的。
但C#编译器实际上会把所有的Linq查询表达式都编译成Linq方法,然后执行。
语法说明:只要where后面的表达式返回的是bool值就行:
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 excellent = from s in students select s.Name;
多属性组合的,可以使用预设类
select new Score { Name = s.Name, Value = s.Score };
也使用匿名对象:
select new { s.Name, s.Score };
majors按Teacher分组,结果可以直接返回:
var result = from m in majors group m by m.Teacher //关键字:group 、by
需要多个属性进行分组的时候:
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() //聚合运算 };
在majors和teachers之间用老师的姓名join:
var result = from m in majors join t in teachers on m.Teacher equals t.Name select m;
语法要点:进行关联时,
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 == "小鱼"
与之相对的,还有(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?
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过滤的)
对应SelectMany()方法:
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);
注意:不要忘记使用返回值赋值!
见:J&C:集合概述 / 迭代器模式 / ER模型 / 仓储模式,注意用Linq表达式实现
多快好省!前端后端,线上线下,名师精讲
更多了解 加: