zoukankan      html  css  js  c++  java
  • 第十二节: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,最终的结果结果相同

     1        DataDBEntities db = new DataDBEntities();
     2             #region 01-where用法
     3             {
     4                 //1. where用法
     5                 //1.1 查询账号为admin的用户信息
     6                 Console.WriteLine("---------------------------- 1. where用法   ----------------------------------------");
     7                 Console.WriteLine("---------------------------- 1.1 查询账号为admin的用户信息   ----------------------------------------");
     8                 List<Sys_UserInfor> sUserList1 = db.Sys_UserInfor.Where(u => u.userAccount == "admin").ToList();
     9                 foreach (var item in sUserList1)
    10                 {
    11                     Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3}", item.userName, item.userAccount, item.userAge, item.userSex);
    12                 }
    13                 //1.2  查询账号为中包含admin且性别为男的用户信息
    14                 Console.WriteLine("---------------------------- 1.2  查询账号为中包含admin且性别为男的用户信息   ----------------------------------------");
    15                 List<Sys_UserInfor> sUserList2 = db.Sys_UserInfor.Where(u => u.userAccount.Contains("admin") && u.userSex == "").ToList();
    16                 foreach (var item in sUserList2)
    17                 {
    18                     Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3}", item.userName, item.userAccount, item.userAge, item.userSex);
    19                 }
    20             }
    21             #endregion

    2. Select用法

      Select中可以查询所有数据,也可以查询指定字段。

           当查询所有数据的时候可以这么写:var sUserList22 = db.Sys_UserInfor.Where(u => u.userAccount.Contains("admin")).Select(u=>u).ToList();  或者直接可以省略Select部分。

      当查询部分数据的时候: 可以用匿名类,也可以用实体。

      即使用匿名类的时候,也可以指定列名,不指定的话,默认和数据库的列名一致。

     1        #region 02-select用法 (匿名类和非匿名类写法)
     2             {
     3                 //2. select用法 (匿名类和非匿名类写法)
     4                 //2.1 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (匿名类的写法,自动生成匿名类名称)
     5                 Console.WriteLine("---------------------------- 2. select用法 (匿名类和非匿名类写法)   ----------------------------------------");
     6                 Console.WriteLine("-------------2.1 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (匿名类的写法)-------------------------");
     7                 var sUserList1 = db.Sys_UserInfor.Where(u => u.userAccount.Contains("admin")).Select(u => new
     8                 {
     9                     u.userName,
    10                     u.userAge,
    11                     u.userSex
    12                 }).ToList();
    13                 sUserList1.ForEach(u =>
    14                 {
    15                     Console.WriteLine("用户名:{0},用户年龄:{1},用户性别:{2}", u.userName, u.userAge, u.userSex);
    16                 });
    17                 //2.2 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (匿名类的写法,指定匿名类名称)
    18                 Console.WriteLine("---------2.2 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (匿名类的写法 指定匿名类名称)--------");
    19                 var sUserList2 = db.Sys_UserInfor.Where(u => u.userAccount.Contains("admin")).Select(u => new
    20                 {
    21                     Name = u.userName,
    22                     Age = u.userAge,
    23                     Sex = u.userSex
    24                 }).ToList();
    25                 sUserList2.ForEach(u =>
    26                 {
    27                     Console.WriteLine("用户名:{0},用户年龄:{1},用户性别:{2}", u.Name, u.Age, u.Sex);
    28                 });
    29                 //2.3 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (非匿名类的写法)
    30                 Console.WriteLine("-------------2.3 查询账号中包含 admin 的用户的 姓名、年龄和性别 三条信息 (非匿名类的写法)-------------------------");
    31                 List<newUserInfor> sUserList3 = db.Sys_UserInfor.Where(u => u.userAccount.Contains("admin")).Select(u => new newUserInfor
    32                 {
    33                     newName = u.userName,
    34                     newAge = u.userAge,
    35                     newSex = u.userSex
    36                 }).ToList();
    37                 sUserList3.ForEach(u =>
    38                 {
    39                     Console.WriteLine("用户名:{0},用户年龄:{1},用户性别:{2}", u.newName, u.newAge, u.newSex);
    40                 });
    41             }
    42             #endregion

    3. OrderBy(OrderByDescending、ThenBy、ThenByDescending)用法

      排序的用法在Lambda、Linq和SQL中相差还是很大的,写法的关键字截然不同。

      在Lambda中:升序: OrderBy→ThenBy→ThenBy

             降序: OrderByDescending→ThenByDescending

           先升序后降序再升序: OrderBy→ThenByDescending→ThenBy

     1       #region 03-OrderBy(OrderByDescending、ThenBy、ThenByDescending)用法
     2             {
     3                 //3. OrderBy(OrderByDescending、ThenBy、ThenByDescending)用法  (单条件升降序、多条件综合排序)
     4                 //3.1 查询delflag 为1 的所有用户信息,按照时间升序排列
     5                 Console.WriteLine("------3. OrderBy(OrderByDescending、ThenBy、ThenByDescending)用法  (单条件升降序、多条件综合排序)-------------");
     6                 Console.WriteLine("--------------------- 3.1 查询delflag 为1 的所有用户信息,按照时间升序排列   ------------------------------");
     7                 List<Sys_UserInfor> sUserList1 = db.Sys_UserInfor.Where(u => u.delFlag == 1).OrderBy(u => u.addTime).ToList();
     8                 foreach (var item in sUserList1)
     9                 {
    10                     Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3},创建时间:{4}", item.userName, item.userAccount, item.userAge, item.userSex, item.addTime);
    11                 }
    12                 //3.2 查询delflag 为1 的所有用户信息,先按照时间升序排列,再按照年龄降序
    13                 Console.WriteLine("---------------3.2 查询delflag 为1 的所有用户信息,先按照时间升序排列,再按照年龄降序----------------------");
    14                 List<Sys_UserInfor> sUserList2 = db.Sys_UserInfor.Where(u => u.delFlag == 1).OrderBy(u => u.addTime).ThenByDescending(u => u.userAge).ToList();
    15                 foreach (var item in sUserList2)
    16                 {
    17                     Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3},创建时间:{4}", item.userName, item.userAccount, item.userAge, item.userSex, item.addTime);
    18                 }
    19             }
    20             #endregion

     

    4. join连接查询

      这里展示的类似全连接的查询,在多表查询,特别是内连接和外链接方面明显不如 Linq和SQL。

     1  #region 04-join连接查询(作用仅限与此么?)
     2             {
     3                 //4. join连接查询(匿名类和非匿名类)
     4                 Console.WriteLine("-------------------- 4. join连接查询(匿名类和非匿名类)------------------------");
     5                 var sUserList = db.Sys_UserInfor;
     6                 var sLoginRecordsList = db.LoginRecords;
     7                 var newList = sUserList.Join(sLoginRecordsList, u => u.id, p => p.userId, (u, p) => new
     8                   {
     9                       UserName = u.userName,
    10                       LoginIp = p.loginIp,
    11                       LoginCity = p.loginCity,
    12                       LoginTime = p.loginTime
    13 
    14                   }).ToList();
    15                 newList.ForEach(a => Console.WriteLine("姓名:{0},登录IP:{1},登录城市:{2},登录时间:{3}", a.UserName, a.LoginIp, a.LoginCity, a.LoginTime));
    16 
    17                 //非匿名类的情况与上述select中的用法相似
    18             } 
    19             #endregion

     

    5. GroupBy分组(匿名类写法)

      这里建议使用var类型接收,原类型太难记忆了,记住一点Lambda和Linq可以把分组依据和分组后对应的数据一次性全部拿出来,但是SQL中分组只能查询分组的依据和使用聚合函数处理其它字段,不能直接查询非分组依据以外的字段。

     1  #region 05-GroupBy分组(匿名类写法)
     2             {
     3                 //5. GroupBy分组(需要重点看一下)
     4                 //5.1 根据用户的性别进行分类,然后将不同性别的用户信息输出来
     5                 Console.WriteLine("-------------------- 5. GroupBy分组------------------------");
     6                 Console.WriteLine("-------------------- 5.1 根据用户的性别进行分类,然后将不同性别的用户信息输出来------------------------");
     7                 var sUserListGroup = db.Sys_UserInfor.GroupBy(u => u.userSex).ToList();
     8                 foreach (var group in sUserListGroup)
     9                 {
    10                     Console.WriteLine("性别为:{0}", group.Key);    //分组依据的字段内容
    11                     foreach (var item in group)
    12                     {
    13                         Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3}", item.userName, item.userAccount, item.userAge, item.userSex);
    14                     }
    15                 }
    16                 //5.2 根据用户性别进行分类,然后将不同性别的年龄大于等于21岁的用户信息输出来
    17                 Console.WriteLine("-------------5.2 根据用户性别进行分类,然后将不同性别的年龄大于等于21岁的用户信息输出来-------------------");
    18                 var sUserListGroup2 = db.Sys_UserInfor.Where(u => u.userAge >= 21).GroupBy(u => u.userSex).ToList();
    19                 foreach (var group in sUserListGroup2)
    20                 {
    21                     Console.WriteLine("性别为:{0}", group.Key);    //分组依据的字段内容
    22                     foreach (var item in group)
    23                     {
    24                         Console.WriteLine("用户名:{0},用户账号:{1},用户年龄:{2},用户性别:{3}", item.userName, item.userAccount, item.userAge, item.userSex);
    25                     }
    26                 }
    27             } 
    28             #endregion

     

    6. Skip和Take用法

      这里结合Skip和Take写分页,太方便了,分页公式:   

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

     

    7. GroupJoin外连接查询(相当于left Join)

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

     
     
     
     

         

  • 相关阅读:
    vue-element-admin实战 | 第二篇: 最小改动接入后台实现根据权限动态加载菜单
    设置git同时推送github和gitee远程仓库
    Spring Cloud实战 | 第一篇:Windows搭建Nacos服务
    winfrom 打开文件夹并定位到指定的文件
    winfrom 关于textbox回车事件有换行的问题
    winfrom切换账号功能
    解决winfrom最大化 窗体被任务栏挡住的问题
    winfrom解决控件闪烁
    winfrom防止程序多开
    c# 对象,IntPtr互转
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/7269089.html
Copyright © 2011-2022 走看看