C#.NET LINQ Lập trình Ứng dụng quản lý 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... Nội dung Các tính năng của .NET 3.0+
Trang 1C#.NET LINQ
Lập trình Ứng dụng quản lý
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
Trang 2Nộ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
Trang 3Cá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
public string Data { get; set; }
string _data;
public string Data
{
get { return _data; }
set { _data = value ; }
}
Trang 4Các tính năng của NET 3.0+ (tt)
Object Initializers
MyClass c = new MyClass { Prop1 = “Value1” , Prop2 = “Value2”
};
class MyClass
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
MyClass c = new MyClass ();
c.Prop1 = “Value1” ;
c.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};
Trang 5Cá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
Nội dung
Extension Method
Query Expression
Khái niệm LINQ
LINQ Query
Trang 6Extension 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 ;
}
}
Trang 7Ví 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 ();
Trang 8Tạ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ó luôn đượ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" ; }
}
Trang 9Extension 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ừ
Không phải tất cả các phương thức của
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 ();
Trang 10Phươ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 % 2 != 0) Reverse ();
Cài đặt thực tế của extension method Where
public static IEnumerable <T> Where < >( 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 < >( IEnumerable <T> source ,
Func <T, bool > predicate ) {
foreach (T item in source )
{
if ( predicate ( item ))
{
yield return item ; }
}
}
Trang 11Phươ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 % 2 != 0) Reverse ()
Select ( => new { Original = x , Sqrt = Math Sqrt ( ) });
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 ( => new { Org = x , Sqr
= x * x })
OrderBy ( => x Sqr) ThenByDescending ( => x Org);
Trang 12Nội dung
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);
where i % 2 == 0 select i;
Trang 13Compiler 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 % 2 == 0)
Select ( => i );
Xét cụ thể hơn trong ví dụ sau:
Có class Test với phương thức Select
public class Test< >
{
public Test<U> Select < >(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 < >( this Test<T> test ,
Func<T, bool > predicate ) {
sb AppendLine ( "Where called " );
return test ;
}
}
Trang 14 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 ToString () == "" )
Select ( => "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
Restriction Where
Projection Select, SelectMany
Partitioning Take, Skip, TakeWhile, SkipWhile
Join Join, GroupJoin
Concatenation Concat
Ordering OrderBy / ThenBy, Reverse
Grouping GroupBy
Set Distinct, Union, Intersect, Except
Conversion ToSequence, ToArray, ToList, ToDictionary, ToLookup, OfType, Cast
Equality EqualAll
Element First, FirstOrDefault, Last, LastOrDefault, Single, SingleOrDefault,
ElementAt, ElementAtOrDefault, DefaultIfEmpty
Generation Range, Repeat, Empty
Quantifiers Any, All, Contains
Trang 15Nội dung
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)
Trang 16Phâ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
Trang 17 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
Trang 18Expression Tree
Vai trò Expression Tree trong LINQ
Nội dung
LINQ Query
Trang 19LINQ 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
Trang 20 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ẻ