前面我們總結Linq查詢子句總共有8個,join子句是我們講解的最后一個子句。join子句也是相對比較復雜的,所以最后來講。join子句可以處理兩個數據源之間的聯系,當然這兩個數據源之間必須存在相關聯的值。
join子句可以實現3中連接關系
1.內部聯接:元素的聯接關系必須同時滿足被連接的兩個數據源
2.分組聯接:含有into子句的join子句
3.左外部聯接
下面我們就詳細的分析一下這三種聯接方式。
准備數據:
除了前面用到的UserBaseInfo類,我們新增一個roles類:
1 using System; 2 using System.Data; 3 using System.Configuration; 4 using System.Linq; 5 using System.Web; 6 using System.Web.Security; 7 using System.Web.UI; 8 using System.Web.UI.HtmlControls; 9 using System.Web.UI.WebControls; 10 using System.Web.UI.WebControls.WebParts; 11 using System.Xml.Linq; 12 using System.Collections; 13 using System.Collections.Generic; 14 15 namespace LinqQueryDemo 16 { 17 /// <summary> 18 /// 角色的基本信息 19 /// </summary> 20 public class RoleInfo 21 { 22 private int id; 23 private string roleName; 24 25 /// <summary> 26 /// 角色的ID值 27 /// </summary> 28 public int ID 29 { 30 get { return id; } 31 set { id = value; } 32 } 33 /// <summary> 34 /// 角色的名稱 35 /// </summary> 36 public string RoleName 37 { 38 get { return roleName; } 39 set { roleName = value; } 40 } 41 42 public RoleInfo(int id, string roleName) 43 { 44 this.id = id; 45 this.roleName = roleName; 46 } 47 } 48 }
內部聯接
內部聯接和sqlserver中的inner join類似,聯接關系必須同時滿足兩個被聯接的數據源。下面代碼中的InnerJoinQuery方法演示了內部聯接users和roles數據源的查詢方法。
1 private void InnerJoinQuery() 2 { 3 4 List<UserBaseInfo> users = new List<UserBaseInfo>(); 5 List<RoleInfo> roles = new List<RoleInfo>(); 6 7 8 for (int i = 1; i < 10; i++) 9 { 10 users.Add(new UserBaseInfo(i, "users0" + i.ToString(), "user0" + i.ToString() + "@web.com", i * 2)); 11 roles.Add(new RoleInfo(i, "RoleName0" + i.ToString())); 12 } 13 14 //查詢ID值小於9,且角色包含roles中的用戶 15 var result = from u in users 16 join r in roles on u.RoleId equals r.ID 17 18 where u.ID < 9 19 select u; 20 21 foreach (var u in result) 22 { 23 24 Response.Write(u.UserName + "</br>"); 25 26 } 27 }
查詢結果:
分組聯接
含有into子句的join子句被分組連接。分組聯接產生分層數據結構。它將第一個集合中的每個元素與第二個集合中的元素進行匹配,在查詢結果中,第一個集合中的元素都會出現,第二個集合中的元素如果匹配成功,則使用被找到的元素否則為空。
下面的groupjoinquery函數演示分組聯接。
1 private void GroupJoinQuery() 2 { 3 4 List<UserBaseInfo> users = new List<UserBaseInfo>(); 5 List<RoleInfo> roles = new List<RoleInfo>(); 6 7 8 for (int i = 1; i < 10; i++) 9 { 10 users.Add(new UserBaseInfo(i, "users0" + i.ToString(), "user0" + i.ToString() + "@web.com", i * 2)); 11 roles.Add(new RoleInfo(i, "RoleName0" + i.ToString())); 12 } 13 14 //查詢ID值小於9,且角色包含roles中的用戶 15 var result = from u in users 16 join r in roles on u.RoleId equals r.ID into g 17 18 where u.ID < 9 19 select new 20 { 21 ID = u.ID, 22 UserName = u.UserName, 23 Email = u.Email, 24 RoleId = u.RoleId, 25 Roles = g.ToList() 26 }; 27 foreach (var u in result) 28 { 29 30 Response.Write(u.UserName +","+(u.Roles.Count>0?u.Roles[0].RoleName:string.Empty)+ "</br>"); 31 32 } 33 }
查詢結果:
左外部聯接
左外部聯接跟sqlserver中的left join相似。他返回第一個集合中的所有元素,第二個集合中與第一個集合相關的元素顯示。如果第二個集合中沒有找到相關的元素,就用DefaultEmpty方法來指定默認值。
1 private void LeftOuterJoinQuery() 2 { 3 4 List<UserBaseInfo> users = new List<UserBaseInfo>(); 5 List<RoleInfo> roles = new List<RoleInfo>(); 6 7 8 for (int i = 1; i < 10; i++) 9 { 10 users.Add(new UserBaseInfo(i, "users0" + i.ToString(), "user0" + i.ToString() + "@web.com", i * 2)); 11 roles.Add(new RoleInfo(i, "RoleName0" + i.ToString())); 12 } 13 14 //查詢ID值小於9,且角色包含roles中的用戶 15 var result = from u in users 16 where u.ID < 9 17 join r in roles on u.RoleId equals r.ID into gr 18 from ur in gr.DefaultIfEmpty() 19 select new 20 { 21 ID = u.ID, 22 UserName = u.UserName, 23 Email = u.Email, 24 RoleId = u.RoleId, 25 Roles = gr.ToList() 26 }; 27 foreach (var u in result) 28 { 29 30 Response.Write(u.UserName +","+(u.Roles.Count>0?u.Roles[0].RoleName:string.Empty)+ "</br>"); 31 32 } 33 }
運行結果: