11/7/2018
Lập trình Ứng dụng quản lý
C#.NET
LINQ
Nội dung
Các tính năng của .NET 3.0+
Extension Method
Query Expression
Khái niệm LINQ
LINQ Query
1
11/7/2018
Nội dung
Các tính năng của .NET 3.0+
Extension Method
Query Expression
Khái niệm LINQ
LINQ Query
Các tính năng của .NET 3.0+
Kiểu dữ liệu không tường minh
2
11/7/2018
Các tính năng của .NET 3.0+ (tt)
Phép khởi tạo tập hợp
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
List<int> list = new List<int>() {1, 2, 3};
Các tính năng của .NET 3.0+ (tt)
Automatic Properties
string _data;
public string Data
{
get { return _data; }
set { _data = value; }
}
public string Data { get; set; }
3
11/7/2018
Các tính năng của .NET 3.0+ (tt)
Object Initializers
class MyClass
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
MyClass c = new MyClass();
c.Prop1 = “Value1”;
c.Prop2 = “Value2”;
MyClass c = new MyClass {
Prop1 = “Value1”,
Prop2 = “Value2”
};
Các tính năng của .NET 3.0+ (tt)
Anonymous Type
var dude = new { Name = “Bob”, Age = 25 };
internal class AnonymousGeneratedTypeName
{
public string Name { get; set; }
public int Age { get; set; }
}
AnonymousGeneratedTypeName dude =
new AnonymousGeneratedTypeName {Name = “Bob”, Age = 25};
4
11/7/2018
Các tính năng của .NET 3.0+ (tt)
Mở rộng phương thức cho lớp đối tượng
Lambda Expression
Expression Trees
Query Expression
LINQ
Nội dung
Các tính năng của .NET 3.0+
Extension Method
Query Expression
Khái niệm LINQ
LINQ Query
5
11/7/2018
Extension Methods
Có từ C# 3.5
Cho phép tạo thêm phương thức cho 1 class mà
không cần tạo class kế thừa. Nói cách khác là
thực thi 1 hàm như là thể hiện phương thức của
lớp đối tượng khác.
Được dùng trong nhu cầu cần thêm một số các
hành xử của đối tượng mà không thể thay đổi
kiểu của đối tượng.
Có thể gọi phương thức từ đối tượng null của
class.
Cách tạo Extension Method
Phương thức để tạo Extension Method phải thỏa các
điều kiện:
Là phương thức static của một static class khơng kế thừa,
khơng generic.
Phải có ít nhất 1 tham số đầu vào.
Tham số đầu tiên phải có từ khóa this theo trước.
Tham số đầu tiên khơng được kèm theo các từ khóa như out,
ref ,… khơng được là kiểu pointer.
Ví dụ:
public static class MyExtensionMethod
{
//extension method cho class object
public static bool isNull(this object obj)
{
return obj == null;
}
}
6
11/7/2018
Ví dụ tình huống sử dụng
Có class SinhVien
public class SinhVien
{
public string HoTen{get;set;}
public int NamSinh{get;set;}
}
Hàm sử dụng class SinhVien
public class SVUlti
{
public static SinhVien SVLonTuoiHon(SinhVien sv1, SinhVien sv2)
{
return (sv1.NamSinh > sv2.NamSinh) ? sv2 : sv1;
}
}
Bây giờ vẫn sử dụng hàm đã có mà cần thêm phương
thức lấy họ của Sinh viên?
Tạo Extension method cho class SinhVien đáp ứng yêu cầu
public static class MyExtensionMethod
{
//extension method cho class SinhVien
public static string LayHoSV(this SinhVien sv)
{
int idx = sv.HoTen.IndexOf(' ');
if (idx == -1)
idx = sv.HoTen.Length;
return sv.HoTen.Substring(0, idx);
}
}
Khi đó có thể sử dụng như sau
var sv1 = new SinhVien { HoTen = "Nguyen Van A", NamSinh = 1992 };
var sv2 = new SinhVien { HoTen = "Tran Thi B", NamSinh = 1993 };
var hoSV = SVUlti.SVLonTuoiHon(sv1, sv2).LayHoSV();
7
11/7/2018
Tạo extension method khác
public static List<string> LayDSHoSV(this List<SinhVien> ds)
{
var l = new List<string>();
foreach (SinhVien sv in ds)
{
l.Add(sv.LayHoSV());
}
return l;
}
public static List<SinhVien> LayDSSVLonTheoNam(this List<SinhVien> ds, int nam)
{
var l = new List<SinhVien>();
foreach (SinhVien sv in ds)
{
if (sv.NamSinh < nam)
{
l.Add(sv);
}
}
return l;
}
Mức độ ưu tiên của Extension Method
Extension method có độ ưu tiên thấp hơn Instance
method. Điều đó có nghĩa là nếu có sự xuất hiện của
Instance method thì nó ln được gọi thay vì Extension
method.
Ví dụ nếu trong class SinhVien ở trên có phương thức
LayHoSV ngay trong class (instance method) thì nó luôn
được sử dụng.
public class SinhVien
{
public string HoTen{get;set;}
public int NamSinh{get;set;}
public string LayHoSV()
{
return "Ho";
}
}
8
11/7/2018
Extension methods trong .NET 3.5
Được sử dụng chủ yếu là cho LINQ.
Chứa đựng chủ yếu trong 2 class chính là:
Enumerable và Queryable.
Hầu hết các phương thức từ Enumerable là xử
lý trên IEnumerable<T> và các phương thức từ
Queryable là xử lý trên IQueryable<T>.
Không phải tất cả các phương thức của
Enumerable và Queryable đều là Extension
method.
Ví dụ
Phương thức Range của Enumerable tạo mảng
các số int theo dạng IEnumerable<int>. Đây là
phương thức tĩnh của chính class.
//tạo mảng {0, 1, 2, 3,..., 9}
IEnumerable<int> lstInt = Enumerable.Range(0, 10);
//sử dụng phương thức mở rộng
lstInt = lstInt.Reverse();
Phương thức Reverse là extension method
của class IEnumerable<T> được cài đặt
trong Enumerable. Do đó có thể viết liền như
sau:
IEnumerable<int> lstInt = Enumerable.Range(0, 10)
.Reverse();
9
11/7/2018
Phương thức mở rộng Where
Là extension method cho class IEnumerable<T>
được cài đặt trong Enumerable.
Cung cấp khả năng lọc (filter) dữ liệu theo điều
kiện mong muốn (Predicate).
Xem cách sử dụng:
//lấy ra các số lẻ của mảng và đảo mảng
var lstInt = Enumerable.Range(0, 10)
.Where(x => x % 2 != 0)
.Reverse();
Cài đặt thực tế của extension method Where
public static IEnumerable<T> Where<T>(this IEnumerable<T> source,
Func<T, bool> predicate)
{
if (source == null || predicate == null)
{
throw new ArgumentNullException();
}
return WhereImpl(source, predicate);
}
private static IEnumerable<T> WhereImpl<T>(IEnumerable<T> source,
Func<T, bool> predicate)
{
foreach (T item in source)
{
if (predicate(item))
{
yield return item;
}
}
}
10
11/7/2018
Phương thức mở rộng Select
Là phương thức thông dụng nhất dùng lấy dữ
liệu trong IEnumerable<T> được cung cấp
extension bởi Enumerable.
Nó xử lý trên IEnumerable<TSource> và đưa dữ
liệu vào IEnumerable<TResult> bằng cách dùng
delegate Func<TSource, TResult>.
Ví dụ:
//lấy ra các đối tượng từ số lẻ của mảng và đảo mảng
var lstInt = Enumerable.Range(0, 10)
.Where(x => x % 2 != 0)
.Reverse()
.Select(x => new { Original = x,
Sqrt = Math.Sqrt(x) });
Phương thức mở rộng OrderBy
Cung cấp khả năng sắp xếp dữ liệu theo tiêu chí
được lựa chọn.
Bao gồm các phương thức: OrderBy,
OrderByDescending, ThenBy,
ThenByDescending.
Ví dụ
//lấy ra các đối tượng từ mảng số và sắp xếp
var dsSN = Enumerable.Range(-5, 11)
.Select(x => new { Org = x, Sqr
= x * x })
.OrderBy(x => x.Sqr)
.ThenByDescending(x => x.Org);
11
11/7/2018
Nội dung
Các tính năng của .NET 3.0+
Extension Method
Query Expression
Khái niệm LINQ
LINQ Query
Query Expression
Ra đời cùng với C# 3.5 nhằm cung cấp cú pháp
(syntax) ngôn ngữ tích hợp (language-integrated) cho
các lệnh truy vấn tương tự như ngôn ngữ truy vấn
quan hệ và phân cấp SQL, XQuery.
Query expression bắt đầu với mệnh đề from và kết
thúc bởi mệnh đề select hoặc group. Nói cách khác
là luôn bắt đầu với một nguồn dữ liệu và kết thúc bởi
các dữ liệu được lựa chọn.
Ví dụ
var lst = Enumerable.Range(0, 11);
var resultQ = from i in lst
where i % 2 == 0
select i;
12
11/7/2018
Compiler translations
Là cơ sở nền tảng của Query expression.
Mục tiêu là thông dịch cú pháp Query expression
sang C# code bình thường.
Ví dụ câu lệnh query expression ở ví dụ trước sẽ
được thơng dịch về dạng
var lst = Enumerable.Range(0, 11);
var resultQ = lst.Where(i => i % 2 == 0)
.Select(i => i);
Xét cụ thể hơn trong ví dụ sau:
Có class Test với phương thức Select
public class Test<T>
{
public Test<U> Select<U>(Func<T, U> selector)
{
MyExtensionMethod.sb.AppendLine("Select called...");
return new Test<U>();
}
}
Xây dựng extension method
public static class MyExtensionMethod
{
public static StringBuilder sb = new StringBuilder();
//extension method cho class Test
public static Test<T> Where<T>(this Test<T> test,
Func<T, bool> predicate)
{
sb.AppendLine("Where called...");
return test;
}
}
13
11/7/2018
Sử dụng query expression
MyExtensionMethod.sb.Clear();
var temp = new Test<int>();
var rs = from test in temp
where test.ToString() == ""
select "test";
Bản chất sau đó được thơng dịch về
rs = temp.Where(x => x.ToString() == "")
.Select(x => "test");
Kết quả trong sb là:
“Where called…
Select called…”
và đối tượng rs là Test<string>.
Query Operators
Bản chất là các extension method
Category
Restriction
Projection
Partitioning
Join
Concatenation
Ordering
Grouping
Set
Where
Select, SelectMany
Take, Skip, TakeWhile, SkipWhile
Join, GroupJoin
Concat
OrderBy / ThenBy, Reverse
GroupBy
Distinct, Union, Intersect, Except
Conversion
ToSequence, ToArray, ToList, ToDictionary, ToLookup, OfType, Cast
Equality
EqualAll
First, FirstOrDefault, Last, LastOrDefault, Single, SingleOrDefault,
ElementAt, ElementAtOrDefault, DefaultIfEmpty
Range, Repeat, Empty
Any, All, Contains
Count, LongCount, Sum, Min, Max, Average, Aggregate
Element
Generation
Quantifiers
Aggregate
Operator
14
11/7/2018
Nội dung
Các tính năng của .NET 3.0+
Extension Method
Query Expression
Khái niệm LINQ
LINQ Query
Khái niệm LINQ
LINQ đọc là LINK, không phải LIN-QUEUE
LINQ: Language Integrated Query
Ra đời từ phiên bản .Net 3.5 gắn liền với
Extension Method và các chức năng lập trình
mới, LINQ đã trở thành “cầu nối để xóa đi
khoảng cách giữa hai thế giới: object và data”.
LINQ cho phép developer thực hiện truy vấn
trên nhiều dạng dữ liệu trong .NET
.NET Objects (List, Queue, Array, …)
Database (DLINQ)
XML (XLINQ)
Parallel LINQ (PLINQ)
15
11/7/2018
Phân loại LINQ
LINQ được chia thành ba loại chính dựa vào đối
tượng sử dụng
LINQ to Objects
LINQ to XML
LINQ-enabled ADO.NET (LINQ to SQL, LINQ to
DataSet và LINQ to Entities)
Có thể bổ sung provider để mở rộng các nguồn dữ
liệu mà LINQ có thể truy vấn
Kiến trúc LINQ
Kiến trúc
16
11/7/2018
Syntax
LINQ syntax
Query syntax
var q1 = from i in arrI
where i % 2 == 0
select i;
Method syntax hay Lambda syntax
var q2 = arrI.Where(i => i % 2 == 0)
.Select(i => i);
Cơ sở của LINQ
Nền tảng của LINQ dựa vào các yếu tố quan
trọng sau
Implicitly typed local variables (cho phép khai
báo biến với kiểu dữ liệu không tường minh)
Object/collection initialization syntax (cú pháp
mới khởi tạo đối tượng, danh sách)
Lambda Expressions
Extension methods
Anonymous types
17
11/7/2018
Expression Tree
Vai trò Expression Tree trong LINQ
Nội dung
Các tính năng của .NET 3.0+
Extension Method
Query Expression
Khái niệm LINQ
LINQ Query
18
11/7/2018
LINQ Query
Một truy vấn là một biểu thức để lấy dữ liệu từ
một nguồn dữ liệu.
Truy vấn thường được thể hiện trong một ngơn
ngữ truy vấn nào đó: SQL – cơ sở dữ liệu quan
hệ, Xquery – XML,…
LINQ đơn giản hóa việc này bằng cách cung cấp
một mơ hình phù hợp để làm việc với dữ liệu trên
các nguồn dữ liệu khác nhau.
Các bước cơ bản
Thực hiện truy vấn LINQ gồm 3 bước cơ bản
Tạo nguồn dữ liệu
Tạo truy vấn
Thực hiện truy vấn
19
11/7/2018
LINQPad
Là chương trình hỗ trợ thực thi LINQ query với
hầu hết các nguồn dữ liệu cơ bản.
Cho phép sử dụng theo cả 2 syntax (Query và
Lambda).
Bài tập làm với LINQPad
Cho mảng: { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }. Tạo mảng
mới sao cho mỗi phần tử đều lớn hơn 1 đơn vị
với mảng đã cho ở vị trí tương ứng.
Cho mảng: { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }. Hãy cho
biết có bao nhiêu số lẻ trong mảng.
Cho mảng số { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }. Hãy
xuất mảng số dưới dạng chuỗi (5 là “five”, 6 là
“six”,…).
Cho mảng: { "aPPLE", "BlUeBeRrY", "cHeRry" }.
Hãy liệt kê mảng với kiểu viết HOA và thường.
Cho mảng: { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }. Hãy xuất
mảng dưới dạng chuỗi và đồng thời cho biết giá
trị là chẵn hay lẻ.
20