Linq 多表連線查詢join
阿新 • • 發佈:2018-12-14
在查詢語言中,通常需要使用聯接操作。在 LINQ 中,可以通過 join 子句實現聯接操作。join 子句可以將來自不同源序列,並且在物件模型中沒有直接關係(資料庫表之間沒有關係)的元素相關聯,唯一的要求是每個源中的元素需要共享某個可以進行比較,以判斷是否相等的值。
在 LINQ 中,join 子句可以實現 3 種類型的聯接分別是內部聯接、分組聯接和左外部聯接。
1、內部連線(相對於sql:join | inner join)
格式:join element in dataSource on exp1 equals exp2
int[] intAry1 = {5, 15, 25, 30, 33, 40};//建立整數陣列 intAry1 作為資料來源 int[] intAry2 = {10, 20, 30, 50, 60, 70, 80};//建立整數陣列 intAry2 作為資料來源 //查詢 query1 使用 join 子句從兩個資料來源獲取資料 //演示內部聯接的使用 var query1 = from val1 in intAry1 join val2 in intAry2 on val1%5 equals val2%15 select new {VAL1=val1, VAL2=val2};
2、分組連線
格式: join element in dataSource on exp1 equals exp2 into grpName
其中,into 關鍵字表示將這些資料分組並儲存到 grpName 中,grpName 是儲存一組資料的集合。(感覺和sql不同,sql查詢的結果是平面矩形的,而linq則是平面樹形的,意思是像物件的元素也是個物件)
int[] intAry1 = { 5, 15, 25, 30, 33, 40 };//建立整數陣列 intAry1 作為資料來源 int[] intAry2 = { 10, 20, 30, 50, 60, 70, 80 };//建立整數陣列 intAry2 作為資料來源 //查詢 query1 使用 join 子句從兩個資料來源獲取資料 //演示分組聯接的使用 var query1 = from val1 in intAry1 join val2 in intAry2 on val1 % 5 equals val2 % 15 into val2Grp select new { VAL1 = val1, VAL2GRP = val2Grp};
3、左外部聯接 (相對於sql:left join | left outer join)
第三種聯接是左外部聯接,它返回第一個集合中的所有元素,無論它是否在第二個集合中有相關元素。在 LINQ 中,通過對分組聯接的結果呼叫 DefaultIfEmpty()方法來執行左外部聯接。DefaultIfEmpty()方法從列表中獲取指定元素。如果列表為空,則返回預設值。
int[] intAry1 = { 5, 15, 23, 30, 33, 40 };//建立整數陣列 intAry1 作為資料來源 int[] intAry2 = { 10, 20, 30, 50, 60, 70, 80 };//建立整數陣列 intAry2 作為資料來源 //查詢 query1 使用 join 子句從兩個資料來源獲取資料 //演示左聯接的使用 var query1 = from val1 in intAry1 join val2 in intAry2 on val1 % 5 equals val2 % 15 into val2Grp from grp in val2Grp.DefaultIfEmpty() select new { VAL1 = val1, VAL2GRP = grp };
查詢方法Lambda示例(GroupJoin):
原形:https://msdn.microsoft.com/zh-cn/library/bb534297(v=vs.105).aspx
public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>( this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector )
過載
public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>( this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer )
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LinqDemo2 { /// <summary> /// 學生實體 /// </summary> public class Student { public int StudentId { get; set; } public string StudentName { get; set; } public int StandardId { get; set; }//水平 } /// <summary> /// 水平/等級 /// </summary> public class Standard { public int StandardId { get; set; } public string StandardName { get; set; }// } class Program { static void Main(string[] args) { #region 資料來源 IList<Student> studentList = new List<Student>() { new Student() {StudentId = 1, StudentName = "John", StandardId = 1}, new Student() {StudentId = 2, StudentName = "Moin", StandardId = 1}, new Student() {StudentId = 3, StudentName = "Bill", StandardId = 2}, new Student() {StudentId = 4, StudentName = "Ram", StandardId = 2}, new Student() {StudentId = 5, StudentName = "Ron"} }; IList<Standard> standardList = new List<Standard>() { new Standard() {StandardId = 1, StandardName = "優秀"}, new Standard() {StandardId = 2, StandardName = "中等"}, new Standard() {StandardId = 3, StandardName = "差生"} }; #endregion //查詢公式 var groupJoin = standardList.GroupJoin(studentList, standard => standard.StandardId, student => student.StandardId, (standard, studentGroup) => new { StandarFullName = standard.StandardName, Students = studentGroup });//感覺和字典型別一樣,一個key,對應一個velue, velue = IEnumerable<Student> //執行查詢 foreach (var item in groupJoin) { Console.WriteLine(item.StandarFullName); foreach (var student in item.Students) { Console.WriteLine(student.StudentName); } } /* 輸出: * 優秀 John Moin 中等 Bill Ram 差生 */ } } }
示例:分頁查詢
var page = 1; var pageSize = 10; var query = (from user in db.Set<User>() join userRole in db.Set<UserRole>() on user.Id equals userRole.UserId join rolePrivilege in db.Set<RolePrivilege>() on userRole.RoleId equals rolePrivilege.RoleId join priviege in db.Set<Privilege>() on rolePrivilege.PrivilegeId equals priviege.Id join role in db.Set<Role>() on userRole.RoleId equals role.Id where user.Id == 1 && userRole.RoleId == 1 orderby user.Id descending select new { user.Id, userRole.RoleId, user.Username, PrivilegeName = priviege.Name, RoleName = role.Name }).Skip((page - 1) * pageSize).Take(pageSize);