>So sánh IQueryable và IEnumerable trong C#

So sánh IQueryable và IEnumerable trong C#

01/03/2023

Như chúng ta đã biết, LINQ - Ngôn ngữ truy vấn tích hợp, được sử dụng để truy vấn dữ liệu từ một tập hợp dữ liệu. Tập hợp dữ liệu có thể là trong cơ sở dữ liệu hoặc collection trên bộ nhớ. Khi sử dụng LINQ, chúng ta có lẽ bắt gặp việc sử dụng IEnumerable và IQueryable rất nhiều nhưng lại chưa hiểu được sự khác biệt giữa chúng. Trong bài viết này, tôi sẽ chia sẻ với các bạn một số điểm lưu ý khi sử dụng 2 interface trên. Cả IQueryable và IEnumerable là các interface trong C# để thao tác với các tập hợp dữ liệu. Tuy nhiên, chúng có một số khác biệt quan trọng về cách thức truy vấn và lấy dữ liệu từ nguồn dữ liệu.

IEnumerable là một interface đơn giản nhất trong số các interface thao tác với tập hợp dữ liệu, nó cung cấp các phương thức để lấy dữ liệu từ một tập hợp dữ liệu, nhưng không cung cấp các phương thức để truy vấn hoặc lọc dữ liệu trước khi lấy. Ngược lại, IQueryable được implement từ IEnumerable nên IQueryable có tất cả các đặc tính của IEnumerable và các đặc tính của riêng nó.

Trong một ví dụ dưới đây sẽ làm rõ hơn vấn đề chúng ta đang nghiên cứu, cụ thể mình có một table Users gồm [UserId], [Fullname] với các dữ liệu đã cho sẵn trước. Và bây giờ mình sẽ code C# để viết 2 khối lệnh tương ứng với 2 interface trên như sau:

 

class Program
    {
        static void Main(string[] args)
        {
            var entities = new DataEntities();

            // Khối lệnh 1
            var enumerableUsers = entities.Users.AsEnumerable().Where(f => f.UserId >= 5).Take(2);
            foreach (var item in enumerableUsers)
            {
                Console.WriteLine(item.UserId);
            }

            // Khối lệnh 2
            var queryableUsers = entities.Users.Where(f => f.UserId >= 5).Take(2);
            foreach (var item in queryableUsers)
            {
                Console.WriteLine(item.UserId);
            }

            Console.ReadKey();
        }
    }

Tiếp theo mở Sql Profile và thấy Sql Engine thực hiện 2 câu lệnh như sau:

Khối 1:

SELECT 
    [Extent1].[UserId] AS [UserId], 
    [Extent1].[Username] AS [Username], 
    FROM [dbo].[Users] AS [Extent1]

Khối 2:

SELECT TOP (2) 
    [Extent1].[UserId] AS [UserId], 
    [Extent1].[Fullname] AS [Fullname], 
    FROM [dbo].[Users] AS [Extent1]
    WHERE [Extent1].[UserId] >= 5

Và bạn thấy đó, khi sử dụng IEnumerable, câu lệnh truy vấn sẽ thực hiện trên máy chủ và trả về dữ liệu cho client, sau khi trả hết dữ liệu, client mới thực hiện lấy 2 bản ghi đầu tiên. Ngược lại, khi sử dụng IQueryable, câu lệnh truy vấn sẽ thực hiện trên máy chủ, lọc trên máy chủ và trả dữ liệu cho client.

Chúng ta hãy xem sự khác nhau giữa 2 interface này:

Namespace

IEnumerable: System.Collections

IQueryable: System.Linq

Truy vấn dữ liệu

IEnumerable: Truy vấn tốt nhất đối với những dữ liệu trên bộ nhớ như List, Array...

IQueryable: Truy vấn tốt nhất đối với những dữ liệu nằm ngoài bộ nhớ như cơ sở dữ liệu.

Cách thức truy vấn

IEnumerable: Truy vấn trên server và trả về dữ liệu cho client. Client sau đấy mới tiếp tục lọc dữ liệu.

IQueryable: Truy vấn và lọc dữ liệu trên server và dữ liệu trả về cho client.

 

Tóm lại, sự khác biệt chính giữa IQueryable và IEnumerable là IQueryable cho phép truy vấn và lọc dữ liệu trước khi lấy, trong khi IEnumerable chỉ cung cấp phương thức để lấy dữ liệu. Tuy nhiên, sử dụng IQueryable có thể tốn nhiều tài nguyên hơn và không phù hợp trong một số trường hợp nhất định.

Theo cá nhân, thì trong một số trường hợp khi sử dụng IEnumerable thích hợp hơn IQueryable là:

  • Khi bạn chỉ cần lấy toàn bộ dữ liệu từ nguồn dữ liệu mà không cần xử lý hay lọc dữ liệu trước khi lấy.

  • Khi tập dữ liệu không lớn và không cần phải tối ưu hiệu suất truy vấn.

  • Khi dữ liệu được lưu trữ trong bộ nhớ và không phải truy vấn từ một nguồn dữ liệu bên ngoài, chẳng hạn như một danh sách trong bộ nhớ hoặc một mảng.

  • Khi bạn cần sử dụng các phương thức mở rộng của IEnumerable như ToList(), ToArray(), hoặc Count() để xử lý dữ liệu.

Trong những trường hợp trên, sử dụng IQueryable có thể không cần thiết và có thể làm giảm hiệu suất hoặc tăng tải cho máy chủ. Tuy nhiên, khi tập dữ liệu lớn và cần phải tối ưu truy vấn, sử dụng IQueryable sẽ giúp cải thiện hiệu suất và giảm tải cho máy chủ.

Và trong thực tế, trong điều kiện số bản ghi của table lớn thì việc sử dụng IEnumerable sẽ ảnh hưởng rất nhiều tới hiệu năng của ứng dụng cũng như của Sql Server.

Chúc bạn vui vẻ..!

Copyright © 2024 by 365learning