Thứ hai, ngày 5 tháng 12 năm 2016

LINQ – Sử dụng Inner Join (C#)

Ngày đăng: 19/3/2012, 12:49:33AM | Lượt xem: 25,331
Hot!

Inner join có tác dụng trả về một tập kết quả từ nhiều tập hợp. Tập kết quả này là giao của các tập hợp được kết dựa trên giá trị (key) so sánh. Trong bài viết này tôi sẽ làm một ví dụ đơn giản để bạn thấy cách truy vấn dữ liệu từ hai tập hợp/bảng, theo hai kiểu cú pháp LINQ là Query Syntax và Method Syntax

Inner join có tác dụng trả về một tập kết quả từ nhiều tập hợp. Tập kết quả này là giao của các tập hợp được kết dựa trên giá trị (key) so sánh. Trong bài viết này tôi sẽ làm một ví dụ đơn giản để bạn thấy cách truy vấn dữ liệu từ hai tập hợp/bảng, theo hai kiểu cú pháp LINQ là Query Syntax và Method Syntax

(Các ví dụ trong bài viết được tôi thực hiện với LINQPad).

Inner Join được minh họa bằng phần giao (màu aqua) của hai tập A và B sau:

Toán tử Join, mệnh đề join và từ khóa equals

Extension method Join() được khai báo dạng sau, dựa vào đây bạn có thể biết Join() được áp dụng cho các đối tượng kiểu IEnumrable<T>. Nếu bạn chưa kiểu về cách sử dụng Func<> có thể coi tại bài viết hướng dẫn về Lambda Expression :

public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>
(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
);

Phương thức Join() có thể được thay thế bởi từ khóa join khi viết theo Query Syntax. Chính xác thì việc xử dụng join phải đi kèm với hai từ khóa khác là onequals, vậy thay vì nói “từ khóa join” ta sẽ gọi là “mệnh đề join”. Cú pháp của mệnh đề join có dạng:

join … on … equals

Mệnh đề join chỉ có thể thực hiện equijoin (join dựa vào so sánh bằng ‘==’), bạn không thể thực hiện các phép so sánh khác như lớn hơn, nhỏ hơn,… để thực hiện một non- equijoin.

equals là một từ khóa/toán tử đặc biệt chỉ được dùng trong mệnh đề join. Bạn không thể bỏ đi hay thay thế từ khóa này bởi một từ khóa, toán tử khác. Từ khóa equals không giống như toán tử ‘==’ trong C#. Với equals, key được dùng so sánh trong vế trái sẽ được so khớp với từng phần tử trong tập hợp bên phải; và tương tự, key bên phải cũng được so khớp với từng phần tử trong tập hợp bên trái (hai chiều).

Một điểm bạn cần lưu ý khi dùng mệnh đề join là tập hợp outer chỉ được hiểu khi ở bên trái của equals, và inner sẽ được dành cho bên phái equals.

Ví dụ Inner Join đơn giản

Để thực hiện ví dụ, tôi tạo hai lớp Product và Category sau. Tôi đặt tên các field của hai lớp này giống như các cột trong các bảng Products và Categories của Northwind database. Điều này giúp bạn dễ hình dung và áp dụng vào LINQ to SQL:

class Product
{
	public int ProductID;
	public string ProductName;
	public int CategoryID;

	public Product(int id, string name, int categoryId)
	{
		this.ProductID=id;
		this.ProductName=name;
		this.CategoryID=categoryId;
	}
}
class Category
{
	public int CategoryID;
	public string CategoryName;

	public Category(int id, string name)
	{
		this.CategoryID=id;
		this.CategoryName=name;
	}
}

Sau đó tạo dữ liệu mẫu cho ví dụ:

var products=new Product[]{
	new Product(1,"PowerPoint",100),
	new Product(2,"Excel",100),
	new Product(3,"Photoshop",101),
};

var categories=new Category[]{
	new Category(100,"Microsoft"),
	new Category(101,"Adobe"),
	new Category(102,"Sun")
};

Và thực hiện truy vấn inner join, ta kết dựa vào giá trị CategoryID để tạo ra một tập kết quả các đối tượng kiểu anonymous (gồm hai giá trị là ProductName và CategoryName) dựa vào toán tử select. Câu truy vấn này được tôi thể hiện dưới 3 dạng sau:

Query Syntax:

var result=from p in products
		join c in categories on p.CategoryID equals c. CategoryID
		select new
		{
			ProductName=p.ProductName,
			CategoryName=c.CategoryName
		};

Method Syntax:

var result=products.Join(
			categories,
			p=>p.CategoryID,
			c=>c.CategoryID,
			(p,c) => new
			{
				ProductName=p.ProductName,
				CategoryName=c.CategoryName
			});

SQL:

SELECT [t0].[ProductName], [t1].[CategoryName]
FROM [Products] AS [t0]
INNER JOIN [Categories] AS [t1] ON [t0].[CategoryID] = ([t1].[CategoryID])

Xem kết quả dưới đây,  bạn thấy rằng category “Sun” không xuất hiện, nguyên nhân là không có Product nào tương ứng với category này.

Table 1:

IEnumerable<> (3 items)

ProductName

CategoryName

PowerPoint

Microsoft

Excel

Microsoft

Photoshop

Adobe

Cơ chế thực hiện

Trong câu lệnh Query Syntax trên, mỗi phần tử trong products được đặt tên là p, và tương ứng c là tên của mỗi phần tử trong categories. Vì Join là một toán tử deffered, khi cần lấy kết quả, từng giá trị p.CategoryID sẽ được so sánh với từng giá trị c.CategoryID, nếu hai giá trị này trùng nhau thì sẽ trả về một đối tượng kết quả mới {ProductName, CategoryName}. Sau khi trả về một đối tượng kết quả, việc so sánh vẫn được tiếp tục và các kết quả mới sẽ trả được trả về nếu như từng cặp giá trị được so sánh khớp nhau.

Bởi vì nguyên tắc của inner join là lấy giao của các tập hợp nên kết quả sẽ không thay đổi nếu thay đổi vị trí của tập hợp outer và inner. Do đó, ta có thể thực hiện câu truy vấn mà không cần quan tâm sẽ dùng tập hợp nào sẽ đứng trước. Câu truy vấn trong ví dụ có thể được viết như sau (thay đổi vị trí của productscategories):

var result=from c in categories
		join p in products on c.CategoryID equals p.CategoryID
		select new
		{
			ProductName=p.ProductName,
			CategoryName=c.CategoryName
		};

Inner Join với mệnh đề from

Bởi vì mục đích của inner join chỉ là lấy giao của hai tập hợp, thay vì dùng mệnh đề join, ta có thể dùng biểu thức truy vấn thông thường. Với cách này, bạn có thể tạo ra được một non- equijoin bằng cách thay đổi toán tử so sánh. Ví dụ trên có thể được viết theo cách sau (equijoin):

var result=from p in products
		from c in categories
		where p.CategoryID==c.CategoryID
		select new
		{
			ProductName=p.ProductName,
			CategoryName=c.CategoryName
		};

Kết quả tương tự như Table 1.

Câu truy vấn LINQ trên tương đương với câu SQL sau:

SELECT [t0].[ProductName], [t1].[CategoryName]
FROM [Products] AS [t0], [Categories] AS [t1]
WHERE [t0].[CategoryID] = ([t1].[CategoryID])

Kết luận

Qua ví dụ này, bạn có thể vận dụng inner join vào LINQ to SQL để truy vấn các bảng dữ liệu. Tuy nhiên điều này chỉ cần thiết khi giữa hai bảng không có relationship. Thông qua ORM, các đối tượng sẽ chứa các tham chiếu tương ứng đến một bảng khác khi có một relationship.

Trong bài này, bạn mới chỉ thấy ví dụ làm việc với hai tập hợp, vì vậy trong bài tiếp theo tôi sẽ cung cấp một ví dụ về Multiple Inner Join sử dụng nhiều mệnh đề join để kết nhiều tập hợp/bảng trong LINQ.

http://yinyangit.wordpress.com

 Chia sẻ qua: 
Hot!
Ý kiến bạn đọc

These items will be permanently deleted and cannot be recovered. Are you sure?

Gallery

image

Maecenas viverra rutrum pulvinar

Maecenas viverra rutrum pulvinar! Aenean vehicula nulla sit amet metus aliquam et malesuada risus aliquet. Vestibulum rhoncus, dolor sit amet venenatis porta, metus purus sagittis nisl, sodales volutpat elit lorem…

Read more

Text Links

Thiết kế logo chuyên nghiệp Insky
DAFABET
W88 w88b.com/dang-ky-tai-khoan-w88
W88
Copyright © 2011 - 2012 vietshare.vn by phamkhuong102@gmail.com doanhkisi2315@gmail.com. All rights reserved.