Linq Series 8- Deferred Execution trong Linq querry | Học trực tuyến CNTT, học lập trình từ cơ bản đến nâng cao

Linq Series 8- Deferred Execution trong Linq querry

Chia sẻ kiến thức 17/04/2023

Deferred Execution trong Linq querry

Xin chào các bạn,trong bài trước chúng ta đã tìm hiểu về cách sử dụng Sử dụng IEnumerable và Method Chaining trong Linq . Hôm nay chúng ta sẽ nói về Deferred Execution trong Linq querry, một kỹ thuật cho phép giải quyết các câu hỏi truy vấn trên cơ sở dữ liệu với sự chậm trễ thực thi cho đến khi kết quả cuối cùng yêu cầu nó được thực hiện.

Giới thiệu về Deferred Execution

Việc thực hiện hoãn lại (Defered Excution) trong Linq nghĩa là việc đánh giá một biểu thức bị trì hoãn cho đến khi giá trị thực sự của nó được yêu cầu. Nó cải thiện đáng kể hiệu suất bằng cách tránh thực hiện không cần thiết.

Việc thực hiện hoãn lại được áp dụng trên mọi collection trong bộ nhớ , LINQ provider như LINQ-to-SQL, LINQ-to-Entities, LINQ-to-XML, v.v.

Hãy hiểu thực thi hoãn lại bằng cách sử dụng ví dụ sau:

Trong ví dụ trên, bạn có thể thấy truy vấn được cụ thể hóa và được thực thi khi bạn lặp lại bằng vòng lặp foreach. Điều này được gọi là thực hiện hoãn lại. LINQ xử lý studentList collection khi bạn thực sự truy cập từng đối tượng từ collection và làm một cái gì đó với nó.

Deferred Execution trả về dữ liệu gần nhất

Để kiểm tra xem việc thực hiện hoãn lại có trả lại dữ liệu mới nhất mỗi lần hay không, ta hãy thêm một biến teenAgerStudents sau vòng lặp foreach và kiểm tra danh sách sinh viên thiếu niên:

Như bạn có thể thấy, vòng lặp foreach thứ hai thực hiện lại truy vấn và trả về dữ liệu mới nhất. Việc thực hiện hoãn lại đánh giá lại trên mỗi lần thực hiện; điều này được gọi là đánh giá lười biếng (lazy evaluation). Đây là một trong những lợi thế chính của việc thực hiện hoãn lại, nó luôn cung cấp cho bạn dữ liệu mới nhất.

Triển khai Deferred Execution

Bạn có thể triển khai thực thi hoãn lại cho các phương thức tiện ích mở rộng tùy chỉnh của mình cho IEnumerable bằng cách sử dụng từ khóa yield của C #.

Ví dụ: bạn có thể triển khai phương thức tiện ích mở rộng tùy chỉnh GetTeenAgerStudents cho IEnumerable trả về danh sách tất cả học sinh là thanh thiếu niên.

public static class EnumerableExtensionMethods
{
    public static IEnumerable<Student> GetTeenAgerStudents(this IEnumerable<Student> source)
    {

        foreach (Student std in source)
        {
            Console.WriteLine("Accessing student {0}", std.StudentName);

            if (std.age > 12 && std.age < 20)
                yield return std;
        }
    }
}

 

Lưu ý rằng chúng ta in tên sinh viên trên màn hình console bất cứ khi nào GetTeenAgerStudents () được gọi.

Bây giờ chúng ta có thể sử dụng phương thức mở rộng này như dưới đây:

IList<Student> studentList = new List<Student>() { 
            new Student() { StudentID = 1, StudentName = "John", age = 13 } ,
            new Student() { StudentID = 2, StudentName = "Steve",  age = 15 } ,
            new Student() { StudentID = 3, StudentName = "Bill",  age = 18 } ,
            new Student() { StudentID = 4, StudentName = "Ram" , age = 12 } ,
            new Student() { StudentID = 5, StudentName = "Ron" , age = 21 } 
        };
            
var teenAgerStudents = from s in studentList.GetTeenAgerStudents() 
                        select s;

foreach (Student teenStudent in teenAgerStudents)
    Console.WriteLine("Student Name: {0}", teenStudent.StudentName);

 

Ta thu được kết quả trên màn hình console như sau:

Accessing student John
Student Name: John
Accessing student Steve
Student Name: Steve
Accessing student Bill
Student Name: Bill
Accessing student Ram
Accessing student Ron

Tự thực hành

Ta có đoạn code:

var animals = new List<string>()
            {
                "Duck","Lion","Dolphin","Tiger"
            };
            var animalsWithD = animals.Where(
                animal =>
                {
                    Console.WriteLine("Check animal: " + animal);
                    return animal.StartsWith('D'); 
                }
                );
            foreach(var animal in animalsWithD)
            {
                Console.WriteLine(animal);
            }
            Console.WriteLine("Hello World!");

Đoạn code trên có mô tả như sau :

  1. Khai báo một list string tên các animal với biến animals
  2. Lọc ra danh sách các animal có tên bắt đầu bằng D với biến animalsWithD và trong mỗi lần lọc in ra kết quả
  3. Duyệt danh sách animal có tên bằng D và in ra tên chúng

Kết quả

Phân tích thì sẽ thấy các đoạn in ra trong khi lọc và trong khi duyệt danh sách thì chúng xen kẽ nhau . Điều này chứng tỏ linq querry không thực hiện nhất thời mà chờ lúc chúng được sử dụng thì mới bắt đầu thực thi.

Tổng kết về Defered Execution trong Linq

  • Deferred execution trong LINQ là một kỹ thuật cho phép giải quyết các câu hỏi truy vấn trên cơ sở dữ liệu với sự chậm trễ thực thi cho đến khi kết quả cuối cùng yêu cầu nó được thực hiện.
  • Nghĩa là khi bạn định nghĩa một truy vấn LINQ và lưu trữ nó trong một biến, chẳng hạn như một đối tượng IQueryable hay IEnumerable, truy vấn đó sẽ không được thực thi ngay lập tức. Thay vào đó, nó sẽ chỉ được thực thi khi bạn yêu cầu kết quả bằng cách lặp lại hoặc gọi phương thức thực thi như ToList(), First(), Count()…
  • Kỹ thuật này cho phép bạn tối ưu hóa truy vấn của mình bằng cách trì hoãn việc thực thi truy vấn đến khi cần thiết, giảm thiểu việc truyền dữ liệu và tài nguyên mạng và giảm thiểu thời gian chờ đợi.
  • Tuy nhiên, cũng cần lưu ý rằng deferred execution có thể gây ra những rắc rối không mong muốn trong trường hợp bạn đã sửa đổi dữ liệu và yêu cầu thực thi trước khi lưu các thay đổi đó. Vì vậy, bạn nên lưu ý thực hiện deferred execution cẩn thận và chỉ khi thực sự cần thiết.

Tài liệu tham khảo

  1. https://github.com/vupt172/linq-series/tree/linq-series-8
  2. https://www.tutorialsteacher.com/linq/linq-deferred-execution

Học viên Phạm Tuấn Vũ

ĐĂNG KÝ TƯ VẤN HỌC LẬP TRÌNH TẠI FUNiX

Bình luận (
0
)

Bài liên quan

  • Tầng 0, tòa nhà FPT, 17 Duy Tân, Q. Cầu Giấy, Hà Nội
  • info@funix.edu.vn
  • 0782313602 (Zalo, Viber)        
Chat Button
Chat với FUNiX GPT ×

yêu cầu gọi lại

error: Content is protected !!