+4

Giới thiệu về LINQ

1. LINQ là gì

Language-Integrated Query, hoặc LINQ là một cách để truy vấn một tập hợp các dữ liệu bằng cách sử dụng các phuơng thức mở rộng (extension methods). những extension methods chỉ có thể truy cập bằng cách thêm using System.Linq;. Trong các ví dụ dưới đây, Bạn sẽ được thấy cách sử dụng LINQ trên List của một Person objects.

Khi bạn làm theo các ví dụ bên dưới, sử dụng List<Person> collection và Person class như sau:

public class Program
{
  public static void Main()
  {
      var people = GenerateListOfPeople();

      // Write your code here
  }

  public static List<Person> GenerateListOfPeople()
  {
      var people = new List<Person>();

      people.Add(new Person { FirstName = "Eric", LastName = "Fleming", Occupation = "Dev", Age = 24 });
      people.Add(new Person { FirstName = "Steve", LastName = "Smith", Occupation = "Manager", Age = 40 });
      people.Add(new Person { FirstName = "Brendan", LastName = "Enrick", Occupation = "Dev", Age = 30 });
      people.Add(new Person { FirstName = "Jane", LastName = "Doe", Occupation = "Dev", Age = 35 });
      people.Add(new Person { FirstName = "Samantha", LastName = "Jones", Occupation = "Dev", Age = 24 });

      return people;
  }
}

public class Person
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string Occupation { get; set; }
  public int Age { get; set; }
}

2. Tìm kiếm item trong collection

Trong nhiều trường hợp, bạn cần công cụ để tìm item trong collection mà đáp ứng một số điều kiện cụ thể, LINQ cung cấp cho bạn các methods như Where, Skip, Take để thực hiện việc này dễ dàng.

2.1 Where

Where là method được dùng phổ biến nhất trong LINQ, Nó có thể dùng để lọc các phần tử trong một collection dựa trên các điều kiện nhất định. Ví dụ: bạn muộn lọc danh sách nhừng người theo điều kiện lớn hơn 30 tuổi. Thì câu lệnh LINQ sẽ như sau:

var peopleOverTheAgeOf30 = people.Where(x => x.Age > 30);

Ở bên trên, chúng ta đã khai báo có 2 người lớn hơn 30 tuổi. Nên kết quả sẽ cho ra 2 người là Steve và Jane.

2.2 Skip

Đôi khi bạn muốn bỏ qua một số phần tử đầu tiên trong collection và chỉ lấy những phần tử còn lại. Skip là method bạn cần dùng trong trường hợp này: Ví dụ dưới đây sẽ bỏ qua hai Item đầu tiên (Eric và Steve) trong List:

IEnumerable<Person> afterTwo = people.Skip(2);

2.3 Take

Ngược với SkipTake, Take sẽ chỉ lấy những phần tử đầu tiên được chọn trong collection với số lượng nằm trong đối số của method. Ví dụ dưới đây sẽ retrun Eric và Steve.

IEnumerable<Person> takeTwo = people.Take(2); 

3 Thay đổi Mỗi Item trong Collection

Một Item trong collection thường có rất nhiều properties. Đôi khi bạn chỉ cần một hoặc một vài properties nhất định. Select sẽ là lựa chọn cho bạn để thực hiện điều này. Ví dụ dưới đây sẽ select FirstName từ mỗi Person trong List<Person> collection và sẽ return một collection String.

IEnumerable<string> allFirstNames = people.Select(x => x.FirstName);

Content của allFirstNames bây giờ sẽ bao gồm các strings "Eric", "Steve", "Brendan", "Jane", "Samantha". Bạn cũng có thể tạo một Đối tượng mới dựa trên các properties mà bạn chọn. Như ví dụ sau: Tạo một model FullName và đặt FirstLast là 2 properties dựa trên FirstNameLastName properties của Person Model.

public class FullName
{
   public string First { get; set; }
   public string Last { get; set; }
}

Đoạn lệnh dưới đây sẽ giải thích việc tạo một object FullName cho mỗi Person trong list:

IEnumerable<FullName> allFullNames = people.Select(x => new FullName { First = x.FirstName, Last = x.LastName });

4 Tìm một Item trong Collections

Ở các ví dụ trên, kết quả trả về luôn là một collection của các object, Trong khi đó, nhiều khi bạn muốn kết quả trả về chỉ là một object lấy từ collections mà thôi. Trong trường hợp này, các method FirstOrDefault, LastOrDefaultSingleOrDefault của LINQ sẽ được sử dụng.

4.1 FirstOrDefault

Method FirstOrDefault sẽ trả về phần tử đầu tiên của collection theo điều kiện, Nếu không có phần tử thoả mãn, kết quả trả về sẽ là default value type của object(thường là null). Ví dụ:

Person firstOrDefault = people.FirstOrDefault();
Console.WriteLine(firstOrDefault.FirstName); //Will output "Eric"

Bạn cũng có thể sử dụng FirstOrDefault kèm theo các điều kiện, nó cũng sẽ trả về phần tử đầu tiên. Ví dụ:

var firstThirtyYearOld1 = people.FirstOrDefault(x => x.Age == 30);
var firstThirtyYearOld2 = people.Where(x => x.Age == 30).FirstOrDefault();
Console.WriteLine(firstThirtyYearOld1.FirstName); //Will output "Brendan"
Console.WriteLine(firstThirtyYearOld2.FirstName); //Will also output "Brendan"

Ta xem xét ví dụ sau trong trường hợp không tìm thấy phần tử phù hợp:

List<Person> emptyList = new List<Person>(); // Empty collection
Person willBeNull = emptyList.FirstOrDefault(); // None - default of null used

List<Person> people = GenerateListOfPeople();
Person willAlsoBeNull = people.FirstOrDefault(x => x.FirstName == "John");  No John - default of null used

Console.WriteLine(willBeNull == null); // true
Console.WriteLine(willAlsoBeNull == null); //true

Ở ví dụ trên, trường hợp một là một collection rỗng, trường hợp 2 không có Person nào có FirstName là "John" (bạn có thể xem ở đầu bài viết để thấy các Person được tạo ở hàm GenerateListOfPeople), cả 2 trường hợp dùng FirstOfDefault đều trả về null.

4.2 LastOfDefault

LastOfDefault tuơng tự với FirstOfDefault, nhưng thay vì trả về phần từ đầu tiên, nó trả về phần tử cuối cùng. Ví dụ:

Person lastOrDefault = people.LastOrDefault();
Console.WriteLine(lastOrDefault.FirstName); //Will output "Samantha"
Person lastThirtyYearOld = people.LastOrDefault(x => x.Age == 30);
Console.WriteLine(lastThirtyYearOld.FirstName); //Will output "Brendan"

4.3 SingleOfDefault

SingleOfDefault sẽ trả về 1 item duy nhất phù hợp với điều kiện, nếu không có Item nào thỏa mãn, default value sẽ được trả về. Tuy nhiên, nếu tìm được nhiều hơn 1 item, 1 exception System.InvalidOperationException sẽ được bắn ra.

Person single = people.SingleOrDefault(x => x.FirstName == "Eric"); //Will return the Eric Person obejct
Person singleDev = people.SingleOrDefault(x => x.Occupation == "Dev"); //Will throw the System.InvalidOperationException

5. Lấy dữ liệu về collection

5.1 Count

Method Count sẽ trả về số lượng Item trong collection với điều kiện được cho. Ví dụ

int numberOfPeopleInList = people.Count(); //Will return 5

Ví dụ trên là tổng số Item trong Collection, ta xem xét một ví dụ có điều kiện:

int peopleOverTwentyFive = people.Count(x => x.Age > 25); //Will return 3

5.2 Any

Any sẽ trả về kiểu dữ liệu Boolean, là true nếu có bất kỳ một Item nào được tìm thấy. Ví dụ:

bool thereArePeople = people.Any(); //This will return true
bool thereAreNoPeople = emptyList.Any(); //This will return false

Sử dụng Any là tốt hơn khi bạn muốn kiếm tra sự tồn tại thay vì Count. ví dụ:

if (people.Count() > 0) //This works
{
    //perform some action(s)
}
if (people.Any()) //This is better
{
    //perform some action(s)
}

5.3 All

Trái ngược với Any, All chỉ trả về True Khi toàn bộ Item thỏa mãn điều kiện. Ví dụ:

bool allDevs = people.All(x => x.Occupation == "Dev"); //Will return false

bool everyoneAtLeastTwentyFour = people.All(x => x.Age >= 24); //Will return true

6. Convert Kết quả trả về thành Collection

Các kết quả trả về của Truy vấn LINQ thường là IEnumerable<T>, Nếu bạn muốn các kiểu dữ liệu khác, bạn có thể dùng các method sau:

6.1 ToList

Method Tolist cho phép bạn convert từ IEnumerable<T> sang List<T>. Ví dụ:

List<Person> listOfDevs = people.Where(x => x.Occupation == "Dev").ToList(); //This will return a List<Person>

6.2 ToArray

Tuơng tự ToList, method ToArray sẽ convert IEnumerable<T> sang T[]. Ví dụ:

Person[] arrayOfDevs = people.Where(x => x.Occupation == "Dev").ToArray(); //This will return a Person[] array

7. Tài liệu Tham Khảo

https://www.microsoft.com/net/tutorials/csharp/getting-started/linq


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.