第十二節:Lambda、linq、SQL的相愛相殺(1)

一. 談情懷html

   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語句spa

  補充Lambad的發展歷史:  3d

  A. 內置委託: new Func<string, int>(delegate(string str) { return str.Length; }); code

  B. 匿名方法: delegate(string str){return str.Length;}htm

  C. lambda語句: (string str)=>{return str.Length;}blog

  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

相關文章
相關標籤/搜索