2012-05-09 33 views
12

Ví dụ:Tôi có thực sự cần sử dụng AsQueryable() trên bộ sưu tập không? đang

List<Student> Students = new List<Student>() 
{ 
    new Student(101, "Hugo", "Garcia", new List<int>() { 91, 88, 76, 93 }), 
    new Student(102, "Rick", "Adams", new List<int>() { 70, 73, 66, 90 }), 
    new Student(103, "Michael", "Tucker", new List<int>() { 73, 80, 75, 88 }), 
    new Student(104, "Fadi", "Fakhouri", new List<int>() { 82, 75, 66, 84 }), 
    new Student(105, "Peter", "Barrows", new List<int>() { 67, 78, 70, 82 }) 
}; 

var query = from student in Students 
      where student.Marks.AsQueryable().All(m => m > 70) 
      select student; 

foreach (Student student in query) 
{ 
    Console.WriteLine("{0} {1}<br />", student.FirstName, student.LastName); 
} 

Nhưng nếu tôi thay đổi truy vấn để

var query = from student in Students 
      where student.Marks.All(m => m > 70) 
      select student; 

này cũng làm việc và tạo ra kết quả tương tự, vì vậy có gì khác biệt?

+0

Câu hỏi tương tự về ['AsEnumerable'] (http://stackoverflow.com/questions/3389855/am-i-misunderstanding-linq-to-sql-asenumerable) – nawfal

Trả lời

7

IQueryable được yêu cầu/đề nghị cho các đối tượng đến từ nguồn từ xa (như từ cơ sở dữ liệu).

Đối với bộ sưu tập bộ nhớ, nó không được sử dụng.

AsQueryable được sử dụng khi cây biểu thức được xây dựng.

Tôi có thể nghĩ về trường hợp phù hợp nhất. Trong ví dụ của bạn, giả sử bạn yêu cầu một số thông tin từ cơ sở dữ liệu dựa trên ID sinh viên.

Bây giờ sinh viên đang ở trong bộ sưu tập bộ nhớ. Bạn cần phải kích hoạt truy vấn cơ sở dữ liệu dựa trên ID sinh viên.

var studentList = Students.Select(s => s.Id).AsQueryAble().Select(i => remoteDBProvider.GetInfo(i)); 

Bất kỳ hoạt động hơn nữa trên studentList sẽ được gọi từ giao diện IQueryable (biểu thức truy vấn), và sẽ lấy chỉ những hồ sơ từ nguồn dữ liệu, mà nên được trả lại kết quả truy vấn cuối cùng (miễn là nguồn dữ liệu, trở lại giá trị của remoteDBProvider.GetInfo trong ví dụ, hỗ trợ QueryProvider).

+5

@BorisB. Đó chỉ đơn giản là không đúng sự thật. [Enumerable.Select] (http://msdn.microsoft.com/en-us/library/bb548891.aspx) cũng sử dụng thực thi hoãn lại. Sự khác biệt là Queryable chấp nhận lambda như một biểu thức. Điều này cho phép nhà cung cấp truy vấn kiểm tra biểu thức và dịch nó thành một cái gì đó (có khả năng) hiệu quả hơn, ví dụ: một truy vấn SQL. Mọi dự đoán hoặc lọc sẽ diễn ra trong cơ sở dữ liệu thay vì trong ứng dụng, tận dụng mã nguồn gốc của cơ sở dữ liệu. Nhưng đối với bộ sưu tập trong bộ nhớ nó không tạo ra sự khác biệt. –

+0

@NielsvanderRest: Bạn nói đúng, bình luận đã bị xóa vì nó gây hiểu nhầm (hoặc đơn giản là không đúng). Tuy nhiên, 'AsQueryable' vẫn sử dụng nó ngay cả đối với bộ sưu tập bộ nhớ, vì phương thức mở rộng' Select' chấp nhận một 'Expression ', cho phép bạn phân tích hoặc sửa đổi nó. Một kịch bản mà tôi có thể nghĩ đến là sử dụng bộ sưu tập trong bộ nhớ được bao bọc trong một 'IQueryable' như là một cách để một lớp không tồn tại lâu dài gửi một truy vấn như là một AST tới một lớp nhận biết liên tục. –

2

Nó phải làm thế nào cây biểu thức được xây dựng. Hãy xem điều này:

AsQueryable là một phương pháp cho phép truy vấn được chuyển đổi thành trường hợp của IQueryable. Khi bạn sử dụng toán tử AsQueryable trên một truy vấn hiện có và áp dụng các phép biến đổi khác như áp dụng bộ lọc hoặc chỉ định thứ tự sắp xếp, các câu lệnh lambda này là được chuyển đổi thành cây biểu thức. Tùy thuộc vào nhà cung cấp bạn đang sử dụng , cây biểu thức sẽ được chuyển đổi thành cú pháp cụ thể của tên miền và được thực hiện. Trong trường hợp của nhà cung cấp LINQ to SQL, cây biểu thức sẽ được chuyển đổi thành SQL và được thi hành trên máy chủ SQL. Tuy nhiên, nếu bạn sử dụng toán tử AsQueryable trên truy vấn không triển khai IQueryable và chỉ triển khai IEnumerable, bất kỳ biến đổi nào bạn áp dụng trên truy vấn sẽ tự động giảm về đặc điểm kỹ thuật IEnumerable. Điều này có nghĩa là bằng cách gắn thẻ truy vấn với AsQueryable bạn nhận được lợi ích của cả LINQ to SQL và LINQ để triển khai đối tượng. Nếu truy vấn hiện tại của bạn xảy ra để triển khai IQueryable, truy vấn được chuyển đổi thành SQL bởi nhà cung cấp LINQ to SQL, nếu không truy vấn được thực hiện trong bộ nhớ dưới dạng mã IL.

Reference here

1

Trong trường hợp của List<Student>, nó không tạo ra bất kỳ sự khác biệt nào, vì trả lại IQueryable<T> sẽ sử dụng cùng một phương pháp để truy vấn như thể bạn chưa từng sử dụng AsQueryable().

Một số phương thức mong đợi thông số IQueryable<T>.Tôi nghĩ rằng phương pháp mở rộng AsQueryable() chủ yếu hữu ích cho những trường hợp đó, khi bạn cần phải vượt qua một số IQueryable<T> nhưng chỉ có một số IEnumerable<T>.

MSDN nói về AsQueryable:

Nếu loại nguồn thực hiện IQueryable<T>, AsQueryable<TElement>(IEnumerable<TElement>) lợi nhuận nó trực tiếp. Nếu không, nó trả về một IQueryable<T> thực hiện truy vấn bằng cách gọi các phương thức toán tử truy vấn tương đương trong Enumerable thay vì các số này trong Queryable.

Vì vậy, đó có nghĩa là trong trường hợp của bạn (List<T> không thực hiện IQueryable<T>), bạn thực sự không cần AsQueryable.

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