2010-03-12 70 views

Trả lời

163

IEnumerable<T> đại diện cho một con trỏ về phía trước chỉ của T. .NET 3.5 đã thêm các phương thức mở rộng bao gồm LINQ standard query operators như WhereFirst, với bất kỳ toán tử nào yêu cầu vị từ hoặc hàm ẩn danh lấy Func<T>.

IQueryable<T> thực hiện cùng một toán tử truy vấn chuẩn LINQ, nhưng chấp nhận Expression<Func<T>> cho các vị từ và hàm ẩn danh. Expression<T> là một cây biểu hiện được biên dịch, một phiên bản bị hỏng của phương thức ("được biên dịch một nửa" nếu bạn muốn) có thể được phân tích cú pháp bởi nhà cung cấp truy vấn và được sử dụng cho phù hợp.

Ví dụ:

IEnumerable<Person> people = GetEnumerablePeople(); 
Person person = people.Where(x => x.Age > 18).FirstOrDefault(); 

IQueryable<Person> people = GetQueryablePeople(); 
Person person = people.Where(x => x.Age > 18).FirstOrDefault(); 

Trong khối đầu tiên, x => x.Age > 18 là một phương pháp vô danh (Func<Person, bool>), có thể được thực hiện giống như bất kỳ phương pháp nào khác. Enumerable.Where sẽ thực thi phương thức một lần cho mỗi người, yield giá trị ing mà phương thức trả về true.

Trong khối thứ hai, x => x.Age > 18 là cây biểu thức (Expression<Func<Person, bool>>), có thể được coi là "thuộc tính 'Độ tuổi'> 18".

Điều này cho phép những thứ như LINQ-to-SQL tồn tại vì chúng có thể phân tích cú pháp cây biểu thức và chuyển đổi nó thành SQL tương đương. Và bởi vì nhà cung cấp không cần thực thi cho đến khi IQueryable được liệt kê (nó thực hiện IEnumerable<T>, sau cùng), nó có thể kết hợp nhiều toán tử truy vấn (trong ví dụ trên WhereFirstOrDefault) để thực hiện các lựa chọn thông minh hơn về cách thực hiện toàn bộ truy vấn so với nguồn dữ liệu cơ bản (như sử dụng SELECT TOP 1 trong SQL).

Xem:

34

"Sự khác biệt chính là các phương pháp mở rộng được xác định cho IQuery có thể biểu diễn đối tượng thay vì đối tượng Func, nghĩa là đại biểu nhận được đó là cây biểu thức thay vì phương thức cần gọi. để làm việc với các bộ sưu tập trong bộ nhớ, nhưng IQueryable cho phép một nguồn dữ liệu từ xa, giống như một cơ sở dữ liệu hoặc web dịch vụ"

nguồn: here

70

Trong cuộc sống thực, nếu bạn đang sử dụng một ORM như LINQ-to-SQL

  • Nếu bạn tạo một IQueryable, sau đó truy vấn có thể được chuyển đổi thành sql và chạy trên máy chủ cơ sở dữ liệu
  • Nếu bạn tạo một IEnumerable, sau đó tất cả các hàng sẽ được đưa vào bộ nhớ dưới dạng đối tượng trước khi chạy truy vấn.

Trong cả hai trường hợp nếu bạn không gọi một ToList() hoặc ToArray() sau đó truy vấn sẽ được thực hiện mỗi lần nó được sử dụng, vì vậy, chẳng hạn, bạn có một IQueryable và bạn đưa vào 4 hộp danh sách từ nó, sau đó truy vấn sẽ được chạy với cơ sở dữ liệu 4 lần.

Ngoài ra nếu bạn mở rộng truy vấn của bạn:

q.Select(x.name = "a").ToList() 

Sau đó, với một IQueryable SQL được tạo ra sẽ chứa where name = "a", nhưng với một IEnumerable nhiều vai trò hơn sẽ được kéo trở lại từ cơ sở dữ liệu, sau đó kiểm tra x.name = "a" sẽ được thực hiện bởi .NET.

+0

"truy vấn có thể được chuyển đổi thành sql": Tôi không nhận được 'có thể'. Ngoài ra, nếu tôi có một IEnumerable và tạo ra một 'chuỗi phức tạp' thì (rõ ràng) không giống như IQueryable, nó sẽ không được dịch sang truy vấn SQL 'tối ưu hóa'. Chỉ muốn xác nhận ý nghĩa của nó khi bạn nói 'tất cả các hàng sẽ được kéo vào bộ nhớ'. Hãy để chúng tôi nói rằng tôi có hai điều khoản, sau đó tất cả các bộ dữ liệu của các thực thể đầu tiên được lấy vào bộ nhớ và sau đó bộ lọc 'trong bộ nhớ' bình thường sẽ xảy ra? – Vaibhav

8

Sự khác biệt về nguyên tắc là IEnumerable sẽ liệt kê tất cả các phần tử của nó mọi lúc, trong khi IEqueryable sẽ liệt kê các phần tử, hoặc thậm chí làm những việc khác, dựa trên truy vấn. Truy vấn là một biểu thức (một biểu diễn dữ liệu của mã .Net), mà một IQueryProvider phải khám phá/giải thích/biên dịch/bất kỳ thứ gì để tạo ra các kết quả.

Có biểu thức truy vấn cung cấp hai lợi thế.

Ưu điểm đầu tiên là tối ưu hóa. Bởi vì các công cụ sửa đổi như 'Where' được bao gồm trong biểu thức truy vấn, IQueryProvider có thể áp dụng các tối ưu hóa không thể khác. Thay vì trả lại tất cả các phần tử, sau đó vứt đi hầu hết trong số chúng do mệnh đề 'Where', nhà cung cấp có thể sử dụng bảng băm để định vị các mục có khóa đã cho.

Ưu điểm thứ hai là tính linh hoạt. Bởi vì Biểu thức là cấu trúc dữ liệu có thể khám phá, bạn có thể làm những việc như sắp xếp theo thứ tự truy vấn và gửi nó đến một máy từ xa (ví dụ: linq-to-sql).

14

IEnumerable IEnumerable phù hợp nhất để làm việc với bộ sưu tập trong bộ nhớ. IEnumerable không di chuyển giữa các mục, nó chỉ chuyển tiếp bộ sưu tập.

IQueryable Bộ thích hợp tốt nhất cho nguồn dữ liệu từ xa, như cơ sở dữ liệu hoặc dịch vụ web. IQueryable là một tính năng rất mạnh mẽ cho phép một loạt các tình huống thực thi trì hoãn thú vị (như truy vấn dựa trên phân trang và thành phần).

Vì vậy, khi bạn phải chỉ đơn giản là lặp qua các bộ sưu tập trong bộ nhớ, sử dụng IEnumerable, nếu bạn cần phải làm bất cứ thao tác với bộ sưu tập như Dataset và các nguồn dữ liệu khác, sử dụng IQueryable

0

Thứ nhất IEnumerable được tìm thấy trong một System.Collections Không gian tên trong khi IQueryable được tìm thấy trong một hệ thống.Linq Namespace. Nếu bạn sử dụng IEnumerable khi truy vấn dữ liệu từ bộ sưu tập trong bộ nhớ như List, Array collection etc Và khi truy vấn dữ liệu từ bộ nhớ ngoài (như cơ sở dữ liệu từ xa, dịch vụ) để bạn sử dụng IQueryable. Bởi vì Trong khi truy vấn dữ liệu từ cơ sở dữ liệu, IEnumerable thực thi truy vấn chọn trên phía máy chủ, tải dữ liệu trong bộ nhớ ở phía máy khách và sau đó lọc dữ liệu. Do đó làm việc nhiều hơn và trở nên chậm chạp. Trong khi truy vấn dữ liệu từ cơ sở dữ liệu, IQueryable thực thi truy vấn chọn trên phía máy chủ với tất cả các bộ lọc. Do đó ít làm việc và trở nên nhanh chóng.

Các vấn đề liên quan