第十二节:Lambda、linq、SQL的相爱相杀(1)
一. 谈情怀
Lambda、Linq、SQL伴随着我的开发一年又一年,但它们三者并没有此消彼长,各自占有这一定的比重,起着不可替代的作用。
相信我们最先接触的应该就是SQL了,凡是科班出身的人,大学期间都会学习SQL Server数据库,当然也会学习SQL语言了(顺便吐槽一下,学校用SQL Server版本真老,好像是2005,我现在都用2016了),补充一点:主流数据库像SQL Sever、MySQL、Oracle某些语句是不同的,在后面介绍分页的时候会有体现。
(1). SQL:是关系型数据库标准语言,其特点:简单,灵活,功能强大。(详细的概念介绍见 数据库概述)
后来在工作中接触到了强大的ORM框架EF,发现了一种写法 db.Sys_UserInfor.Where(u => u.userAccount == "admin").ToList(); 彻底颠覆了我的三观,查询数据库,竟然可以这么简单,后来查询了一下,这个东西叫Lambda。
(2). Lambda:是比匿名方法更简洁的一种语法,包括 Lambda表达式 和 Lambda语句 。
补充Lambad的发展历史:
A. 内置委托: new Func<string, int>(delegate(string str) { return str.Length; });
B. 匿名方法: delegate(string str){return str.Length;}
C. lambda语句: (string str)=>{return str.Length;}
D. lambda表达式: (string str)=> str.Length
E.让编译器推断类型: (str)=> str.Length
F. 去掉不必要的括弧: str=> str.Length
注意:Lambda语句 和 Lambda表达式 的区别在于,前者在 =>右边有一个语句块(大括号),而后者只有一个表达式(没有return 和大括号)。Lambda本身无类型,所以不能赋值给 var 变量。编译时会生成一个静态方法, 然后再实例化成委托传递。
1. Lambda表达式: list.FindAll(d => d.Id > 2); 又名:点标记。
2. Lambda语句:list.ForEach(d => { if (d.Id > 2) { Response.Write(d.ToString()); } });
(3). Linq:是最接近SQL语言的一种查询表达式,又称语言集成查询,它是C# 3.0 时代的产物。
它与SQL写法上的本质区别是: linq是以from开头 select 或group by结尾。
二. 数据准备
我们准备两张表 用户表Sys_UserInfor和用户登录记录表LoginRecords。
表结构:


表数据:


三. Lambda开篇
1. Where用法
Where用法相对比较简单,多个并列条件可以在一个Where中用&&符号链接,也可以写过个Where,最终的结果结果相同
DataDBEntities db = new DataDBEntities();
#region 01-where用法
{
//1. where用法
//1.1 查询账号为admin的用户信息
Console.WriteLine("---------------------------- 1. where用法 ----------------------------------------");
Console.WriteLine("---------------------------- 1.1 查询账号为admin的用户信息 ----------------------------------------");
List<Sys_UserInfor> sUserList1 = db.Sys_UserInfor.Where(u => u.userAccount == "admin").ToList();
foreach (var item in sUserList1)
{
Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3}", item.userName, item.userAccount, item.userAge, item.userSex);
}
//1.2 查询账号为中包含admin且性别为男的用户信息
Console.WriteLine("---------------------------- 1.2 查询账号为中包含admin且性别为男的用户信息 ----------------------------------------");
List<Sys_UserInfor> sUserList2 = db.Sys_UserInfor.Where(u => u.userAccount.Contains("admin") && u.userSex == "男").ToList();
foreach (var item in sUserList2)
{
Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3}", item.userName, item.userAccount, item.userAge, item.userSex);
}
}
#endregion

2. Select用法
Select中可以查询所有数据,也可以查询指定字段。
当查询所有数据的时候可以这么写:var sUserList22 = db.Sys_UserInfor.Where(u => u.userAccount.Contains("admin")).Select(u=>u).ToList(); 或者直接可以省略Select部分。
当查询部分数据的时候: 可以用匿名类,也可以用实体。
即使用匿名类的时候,也可以指定列名,不指定的话,默认和数据库的列名一致。
#region 02-select用法 (匿名类和非匿名类写法)
{
//2. select用法 (匿名类和非匿名类写法)
//2.1 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (匿名类的写法,自动生成匿名类名称)
Console.WriteLine("---------------------------- 2. select用法 (匿名类和非匿名类写法) ----------------------------------------");
Console.WriteLine("-------------2.1 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (匿名类的写法)-------------------------");
var sUserList1 = db.Sys_UserInfor.Where(u => u.userAccount.Contains("admin")).Select(u => new
{
u.userName,
u.userAge,
u.userSex
}).ToList();
sUserList1.ForEach(u =>
{
Console.WriteLine("用户名:{0},用户年龄:{1},用户性别:{2}", u.userName, u.userAge, u.userSex);
});
//2.2 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (匿名类的写法,指定匿名类名称)
Console.WriteLine("---------2.2 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (匿名类的写法 指定匿名类名称)--------");
var sUserList2 = db.Sys_UserInfor.Where(u => u.userAccount.Contains("admin")).Select(u => new
{
Name = u.userName,
Age = u.userAge,
Sex = u.userSex
}).ToList();
sUserList2.ForEach(u =>
{
Console.WriteLine("用户名:{0},用户年龄:{1},用户性别:{2}", u.Name, u.Age, u.Sex);
});
//2.3 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (非匿名类的写法)
Console.WriteLine("-------------2.3 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (非匿名类的写法)-------------------------");
List<newUserInfor> sUserList3 = db.Sys_UserInfor.Where(u => u.userAccount.Contains("admin")).Select(u => new newUserInfor
{
newName = u.userName,
newAge = u.userAge,
newSex = u.userSex
}).ToList();
sUserList3.ForEach(u =>
{
Console.WriteLine("用户名:{0},用户年龄:{1},用户性别:{2}", u.newName, u.newAge, u.newSex);
});
}
#endregion

3. OrderBy(OrderByDescending、ThenBy、ThenByDescending)用法
排序的用法在Lambda、Linq和SQL中相差还是很大的,写法的关键字截然不同。
在Lambda中:升序: OrderBy→ThenBy→ThenBy
降序: OrderByDescending→ThenByDescending
先升序后降序再升序: OrderBy→ThenByDescending→ThenBy
#region 03-OrderBy(OrderByDescending、ThenBy、ThenByDescending)用法
{
//3. OrderBy(OrderByDescending、ThenBy、ThenByDescending)用法 (单条件升降序、多条件综合排序)
//3.1 查询delflag 为1 的所有用户信息,按照时间升序排列
Console.WriteLine("------3. OrderBy(OrderByDescending、ThenBy、ThenByDescending)用法 (单条件升降序、多条件综合排序)-------------");
Console.WriteLine("--------------------- 3.1 查询delflag 为1 的所有用户信息,按照时间升序排列 ------------------------------");
List<Sys_UserInfor> sUserList1 = db.Sys_UserInfor.Where(u => u.delFlag == ).OrderBy(u => u.addTime).ToList();
foreach (var item in sUserList1)
{
Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3},创建时间:{4}", item.userName, item.userAccount, item.userAge, item.userSex, item.addTime);
}
//3.2 查询delflag 为1 的所有用户信息,先按照时间升序排列,再按照年龄降序
Console.WriteLine("---------------3.2 查询delflag 为1 的所有用户信息,先按照时间升序排列,再按照年龄降序----------------------");
List<Sys_UserInfor> sUserList2 = db.Sys_UserInfor.Where(u => u.delFlag == ).OrderBy(u => u.addTime).ThenByDescending(u => u.userAge).ToList();
foreach (var item in sUserList2)
{
Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3},创建时间:{4}", item.userName, item.userAccount, item.userAge, item.userSex, item.addTime);
}
}
#endregion

4. join连接查询
这里展示的类似全连接的查询,在多表查询,特别是内连接和外链接方面明显不如 Linq和SQL。
#region 04-join连接查询(作用仅限与此么?)
{
//4. join连接查询(匿名类和非匿名类)
Console.WriteLine("-------------------- 4. join连接查询(匿名类和非匿名类)------------------------");
var sUserList = db.Sys_UserInfor;
var sLoginRecordsList = db.LoginRecords;
var newList = sUserList.Join(sLoginRecordsList, u => u.id, p => p.userId, (u, p) => new
{
UserName = u.userName,
LoginIp = p.loginIp,
LoginCity = p.loginCity,
LoginTime = p.loginTime }).ToList();
newList.ForEach(a => Console.WriteLine("姓名:{0},登录IP:{1},登录城市:{2},登录时间:{3}", a.UserName, a.LoginIp, a.LoginCity, a.LoginTime)); //非匿名类的情况与上述select中的用法相似
}
#endregion

5. GroupBy分组(匿名类写法)
这里建议使用var类型接收,原类型太难记忆了,记住一点Lambda和Linq可以把分组依据和分组后对应的数据一次性全部拿出来,但是SQL中分组只能查询分组的依据和使用聚合函数处理其它字段,不能直接查询非分组依据以外的字段。
#region 05-GroupBy分组(匿名类写法)
{
//5. GroupBy分组(需要重点看一下)
//5.1 根据用户的性别进行分类,然后将不同性别的用户信息输出来
Console.WriteLine("-------------------- 5. GroupBy分组------------------------");
Console.WriteLine("-------------------- 5.1 根据用户的性别进行分类,然后将不同性别的用户信息输出来------------------------");
var sUserListGroup = db.Sys_UserInfor.GroupBy(u => u.userSex).ToList();
foreach (var group in sUserListGroup)
{
Console.WriteLine("性别为:{0}", group.Key); //分组依据的字段内容
foreach (var item in group)
{
Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3}", item.userName, item.userAccount, item.userAge, item.userSex);
}
}
//5.2 根据用户性别进行分类,然后将不同性别的年龄大于等于21岁的用户信息输出来
Console.WriteLine("-------------5.2 根据用户性别进行分类,然后将不同性别的年龄大于等于21岁的用户信息输出来-------------------");
var sUserListGroup2 = db.Sys_UserInfor.Where(u => u.userAge >= ).GroupBy(u => u.userSex).ToList();
foreach (var group in sUserListGroup2)
{
Console.WriteLine("性别为:{0}", group.Key); //分组依据的字段内容
foreach (var item in group)
{
Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3}", item.userName, item.userAccount, item.userAge, item.userSex);
}
}
}
#endregion

6. Skip和Take用法
这里结合Skip和Take写分页,太方便了,分页公式:
data.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
补充MySQL数据中特有的分页,也很方便,分页公式:SELECT * FROM 表名 LIMIT (pageIndex-1)*pageSize,pageSize .
#region 06-Skip和Take用法
{
//6. Skip和Take 分页用法
//skip表示跳过多少条,Take表示取多少条
//6.1 根据时间降序排列,取第2和第3条数据(即先排序,然后跨过1条,取2条数据)
Console.WriteLine("--------------------6. Skip和Take 分页用法------------------------");
Console.WriteLine("---------6.1 根据时间降序排列,取第2和第3条数据(即先排序,然后跨过1条,取2条数据)---------");
var sUserList = db.Sys_UserInfor.OrderByDescending(u => u.addTime).Skip().Take().ToList();
sUserList.ForEach(u =>
{
Console.WriteLine("用户名:{0},用户年龄:{1},用户性别:{2},创建时间:{3}", u.userName, u.userAge, u.userSex, u.addTime);
}); // 6.2 分页公式
// 每页两条数据,根据时间降序,取第三页的所有数据
Console.WriteLine("---------6.2 每页两条数据,根据时间降序,取第三页的所有数据---------");
var sUserList2 = GetDataByIndex(db.Sys_UserInfor.OrderByDescending(u => u.addTime).ToList(), , );
sUserList2.ForEach(u =>
{
Console.WriteLine("用户名:{0},用户年龄:{1},用户性别:{2},创建时间:{3}", u.userName, u.userAge, u.userSex, u.addTime);
});
}
#endregion
#region 分页公式
static List<Sys_UserInfor> GetDataByIndex(List<Sys_UserInfor> data, int pageIndex, int pageSize)
{
return data.Skip((pageIndex - ) * pageSize).Take(pageSize).ToList();
}
#endregion

7. GroupJoin外连接查询(相当于left Join)
#region 06-GroupJoin外连接查询(相当于left Join)
{
Console.WriteLine("-------------------- 06-GroupJoin多表关联分组------------------------");
Console.WriteLine("--------------------根据性别分组,输出相同性别的用户和登录城市 ------------------------");
var list = db.Sys_UserInfor.GroupJoin(db.LoginRecord2, (Sys_UserInfor a) => a.id, (LoginRecord2 b) => b.userId, (m,n) => new
{
m.userName,
n
}).ToList(); foreach (var item in list)
{
var userName = item.userName;
foreach (var cItem in item.n.ToList())
{
Console.WriteLine("用户名为{0}的用户的登录城市是:{1},登录时间是:{2}", userName, cItem.loginCity,cItem.loginTime);
}
}
}
#endregion

第十二节:Lambda、linq、SQL的相爱相杀(1)的更多相关文章
- 第十三节:Lambda、linq、SQL的相爱相杀(2)
一. Linq开篇 1.Where用法 linq中where的用法与SQL中where的用法基本一致. #region 01-where用法 { //1. where用法 //1.1 查询账号为adm ...
- 第十四节:Lambda、linq、SQL的相爱相杀(3)
一. SQL 开篇 1. where用法 #region 封装EF调用SQL语句查询 public static List<T> ExecuteQuery<T>(string ...
- 阿里云CDN技术掌舵人文景:相爱相杀一路狂奔的这十年
导读:提到阿里云CDN,不得不提技术掌舵人姚伟斌(文景),虽然他不是团队中最“老”的同学,但他却历经了淘宝业务发展最为飞速的几年,见证了从最初服务淘宝和集团内部的CDN,到如今国内服务客户最多的云CD ...
- 猎豹CEO傅盛:与周鸿祎、雷军、马化腾、马云的的相爱相杀
百度百科:傅盛,男,1978年3月6日出生在江西景德镇,毕业于山东工商学院信息管理与信息系统专业. 2003年加入3721公司.2005年加入奇虎360,带领团队打造了安全类软件360安全卫士.200 ...
- rem与px的相爱相杀
rem 简介:为元素设定字体大小:相对大小:只相对HTML根元素. 优点:只修改根元素就可以成比例调整所有字体的大小. bug:IE8及更早版本不兼容. hack:多写一个绝对单位px的声明,不兼容版 ...
- 我与UML相爱相杀的狗血日常
前言 该怎么说呢,在专业母亲的包办婚姻和我不得不为日后的百万家产[日后的百万年薪,我怕是在做梦]下,我和UML的婚后生活正式开始了.第一天回娘家我亓老师就给出了她最爱的编程作业.说实话,我当初以头发为 ...
- GoPath模式和GoMoudle模式的相爱相杀
相信看我文章的文章的童鞋,golang版本已经是1.3版本以上.如果你的版本还停留在1.3以下,那这篇文章可以做为你的提升之法. go moudle的前世今生 前世-gopath gopath是什么 ...
- React关于constructor与super(props)之间的相爱相杀
我们先把菜鸟教程的一段代码拿过来分析一下.下面这段代码是用了将生命周期方法添加到类中实现时钟效果. // 将生命周期方法添加到类中 class Clock extends React.Componen ...
- ASP.NET连接数据库时,提示“用户 'sa' 登录失败原因: 未与信任 SQL Server 连接相关联
用ASP.NET连接数据库时,提示"用户 'sa' 登录失败.原因: 未与信任 SQL Server 连接相关联.".解决方法:首先检查是不是web.config文件内的用户名密码 ...
随机推荐
- Github上如何查看当前最流行的开源项目
先声明下:只针对初学者,大神的话勿喷. 针对题标的这个问题,按照如下步骤操作即可: 进入Github网站后,显示的页面如下所示: 点击"Explore"链接,进入如下页面: 页面上 ...
- Linux Collection:文本编辑问题
PAS 删除文本中的^M标记 由于历史原因,不同操作系统使用不同的方式表示文件的换行符\n.现代计算机系统中的文件换行和早期的打字机有关,主要和两个控制符有关:line feed (LF) ,carr ...
- Postman安装及入门教程
安装 本文只是基于 Chrome 浏览器的扩展插件来进行的安装,并非单独应用程序. 首先,你要台电脑,其次,安装有 Chrome 浏览器,那你接着往下看吧. 1. 官网安装(别看) 打开官网,http ...
- python 结巴分词学习
结巴分词(自然语言处理之中文分词器) jieba分词算法使用了基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能生成词情况所构成的有向无环图(DAG), 再采用了动态规划查找最大概率路径,找出基于 ...
- python接口自动化-get请求
一.环境安装 1.用pip安装requests模块 >>pip install requests 二.get请求 1. url 1.1: response 的返回内容还有很多信息,例 ...
- Vmware10中Centos7挂载Windows主机的共享文件夹,提示:Error: cannot mount filesystem: No such device
1.设置共享权限 2.安装VMware tools 点击虚拟机 点击安装 VMware tools 将/run/media/zhaojq/VMware\ Tools 目录下的VMwareTools-9 ...
- [LeetCode] 16. 最接近的三数之和
题目链接:https://leetcode-cn.com/problems/3sum-closest/ 题目描述: 给定一个包括 n 个整数的数组 nums 和 一个目标值 target.找出 num ...
- JavaScript简单了解
一.JavaScript 的诞生历史 在最初的时候 JS 主要解决的问题是一些服务器端语言(perl)对数据的 验证功能,在js 出现之前要对表单的数据进行验证需要将数据提交到服务器 端之后才能验证数 ...
- 一文搞懂Raft算法
raft是工程上使用较为广泛的强一致性.去中心化.高可用的分布式协议.在这里强调了是在工程上,因为在学术理论界,最耀眼的还是大名鼎鼎的Paxos.但Paxos是:少数真正理解的人觉得简单,尚未理解 ...
- 【重磅】FineUIPro基础版免费,是时候和ExtJS说再见了!
三石的新年礼物 9 年了,FineUI(开源版)终于迎来了她的继任者 - FineUIPro(基础版),并且完全免费! FineUIPro(基础版)作为三石奉献给社区的一个礼物,绝对让你心动: 拥 ...