Ngôn ngữ LINQ - Toán tử GroupJoin
Toán tử GroupJoin trong LINQ
Chúng ta đã tìm hiểu về toán tử Join trong phần trước. Toán tử GroupJoin thực hiện nhiệm vụ tương tự như toán tử Join ngoại trừ GroupJoin trả về một kết quả trong nhóm dựa trên khóa nhóm được chỉ định.
Phương thức GroupJoin trong Cú pháp phương thức
Toán tử GroupJoin ghép nối hai danh sách dựa trên khóa bằng cách khớp khóa của hai danh sách và trả về tập hợp kết quả là một danh sách gồm khóa và danh sách được nhóm.
GroupJoin giống như LEFT OUTER JOIN của SQL.
GroupJoin yêu cầu các tham số tương tự như Join. GroupJoin có hai phương thức quá tải sau:
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);
Ví dụ dưới đây minh họa phương thức mở rộng GroupJoin sử dụng cú pháp phương thức LINQ:
// Student collection
IList<Student> studentList = new List<Student>()
{
new Student() { StudentID = 1, StudentName = "John", Age = 18, StandardID = 1 },
new Student() { StudentID = 2, StudentName = "Steve", Age = 21, StandardID = 1 },
new Student() { StudentID = 3, StudentName = "Bill", Age = 18, StandardID = 2 },
new Student() { StudentID = 4, StudentName = "Ram", Age = 20, StandardID = 2 },
new Student() { StudentID = 5, StudentName = "Ron", Age = 21 }
};
IList<Standard> standardList = new List<Standard>()
{
new Standard(){ StandardID = 1, StandardName="Standard 1"},
new Standard(){ StandardID = 2, StandardName="Standard 2"},
new Standard(){ StandardID = 3, StandardName="Standard 3"}
};
var groupJoin = standardList.GroupJoin(studentList, //inner sequence
std => std.StandardID, //outerKeySelector
s => s.StandardID, //innerKeySelector
(std, studentsGroup) => new // resultSelector
{
Students = studentsGroup,
StandarFulldName = std.StandardName
});
foreach (var item in groupJoin)
{
Console.WriteLine("{0}:", item.StandarFulldName);
foreach(var stud in item.Students)
{
Console.WriteLine("- {0}", stud.StudentName);
}
}
Đây là kết quả khi biên dịch và thực thi chương trình:
Standard 1:
- John
- Steve
Standard 2:
- Bill
- Ram
Standard 3:
Trong ví dụ trên của truy vấn GroupJoin, standardList là danh sách bên ngoài, vì truy vấn bắt đầu từ nó. Tham số đầu tiên trong phương thức GroupJoin chỉ định danh sách bên trong - chính là studentList.
Tham số thứ hai và thứ ba của phương thức GroupJoin được sử dụng để chỉ định trường có giá trị khớp với biểu thức lambda để đưa phần tử vào kết quả.
Biểu thức student => student.StandardID
lấy trường StandardID của từng phần tử trong studentList làm khóa.
Biểu thức standard => standard.StandardID
lấy trường StandardID của từng phần tử trong standardList làm khóa
Nếu giá trị của cả hai khóa này khớp với nhau thì phần tử đó được đưa vào nhóm danh sách kết quả.
Tham số cuối cùng trong phương thức GroupJoin là một biểu thức để tạo kết quả. Trong ví dụ trên, kết quả trả về là một kiểu ẩn danh bao gồm thuộc tính StandardName và Students (danh sách sinh viên theo StandardID).
Hình ảnh sau đây minh họa rằng danh sách bên trong được đưa vào danh sách studentsGroup để khớp với khóa StandardID và nó có thể được sử dụng để tạo kết quả.
Tập kết quả sẽ bao gồm một đối tượng ẩn danh có các thuộc tính Students và StandardFullName. Thuộc tính Students là một danh sách các Student có StandardID khớp với Standard.StandardID.
Mệnh đề GroupJoin trong Cú pháp truy vấn
Toán tử GroupJoin trong cú pháp truy vấn hoạt động hơi khác so với cú pháp phương thức. Nó đòi hỏi một danh sách bên ngoài, danh sách bên trong, bộ chọn khóa và bộ chọn kết quả.
Từ khóa on
được sử dụng cho bộ chọn khóa trong đó phía bên trái của toán tử equals
là khóa của danh sách bên ngoài (outerKey) và bên phải của nó là khóa của danh sách bên trong (innerKey).
Dưới đây là cú pháp của mệnh đề GroupJoin trong cú pháp truy vấn LINQ.
from ... in outerSequence
join ... in innerSequence on outerKey equals innerKey
into groupedCollection
select ...
Ví dụ sau đây cho thấy GroupJoin trong cú pháp truy vấn.
// Student collection
IList<Student> studentList = new List<Student>()
{
new Student() { StudentID = 1, StudentName = "John", Age = 18, StandardID = 1 },
new Student() { StudentID = 2, StudentName = "Steve", Age = 21, StandardID = 1 },
new Student() { StudentID = 3, StudentName = "Bill", Age = 18, StandardID = 2 },
new Student() { StudentID = 4, StudentName = "Ram", Age = 20, StandardID = 2 },
new Student() { StudentID = 5, StudentName = "Ron", Age = 21 }
};
IList<Standard> standardList = new List<Standard>()
{
new Standard(){ StandardID = 1, StandardName="Standard 1"},
new Standard(){ StandardID = 2, StandardName="Standard 2"},
new Standard(){ StandardID = 3, StandardName="Standard 3"}
};
var groupJoin = from std in standardList
join s in studentList on std.StandardID equals s.StandardID
into studentGroup
select new
{
Students = studentGroup,
StandarFulldName = std.StandardName
};
foreach (var item in groupJoin)
{
Console.WriteLine(item.StandarFulldName );
foreach(var stud in item.Students)
{
Console.WriteLine(stud.StudentName);
}
}
Đây là kết quả khi biên dịch và thực thi chương trình:
Standard 1:
- John
- Steve
Standard 2:
- Bill
- Ram
Standard 3:
Lưu ý: Sử dụng toán tử equals để khớp với bộ chọn khóa. Toán tử ==
không hợp lệ.