2010-06-14 19 views
37

Tôi biết điều này có thể là ý kiến, nhưng tôi đang tìm các phương pháp hay nhất.Tôi có nên trả lại số điện thoại <T> hoặc IQueryable <T> từ DAL của tôi không?

Theo tôi được biết, thực hiện IQueryable<T>IEnumerable<T>, vì vậy trong Dal của tôi, Tôi hiện đang có chữ ký phương pháp như sau:

IEnumerable<Product> GetProducts(); 
IEnumerable<Product> GetProductsByCategory(int cateogoryId); 
Product GetProduct(int productId); 

Tôi có nên sử dụng IQueryable<T> đây?

Ưu và nhược điểm của một trong hai cách tiếp cận là gì?

Lưu ý rằng tôi đang lên kế hoạch về việc sử dụng các mẫu Repository vì vậy tôi sẽ có một lớp như vậy:

public class ProductRepository { 

    DBDataContext db = new DBDataContext(<!-- connection string -->); 

    public IEnumerable<Product> GetProductsNew(int daysOld) { 
     return db.GetProducts() 
      .Where(p => p.AddedDateTime > DateTime.Now.AddDays(-daysOld)); 
    } 
} 

Tôi có nên thay đổi của tôi IEnumerable<T>-IQueryable<T>? Những lợi thế/bất lợi là có một hay khác?

Trả lời

49

Tùy thuộc vào hành vi bạn muốn.

  • Việc trả lại IList <T> nói với người gọi rằng họ đã nhận được tất cả các dữ liệu mà họ đã yêu cầu
  • Việc trả lại IEnumerable <T> nói với người gọi rằng họ sẽ cần phải lặp lại kết quả và nó có thể được tải một cách lười biếng.
  • Trả lại IQueryable <T> cho người gọi biết kết quả được hỗ trợ bởi nhà cung cấp LINQ có thể xử lý các lớp truy vấn nhất định, đặt gánh nặng cho người gọi để tạo truy vấn thực hiện.

Trong khi sau này cung cấp cho người gọi rất nhiều tính linh hoạt (giả định kho lưu trữ của bạn hỗ trợ đầy đủ), thì khó nhất để kiểm tra và được cho là ít xác định nhất.

+0

Độc đáo nói. Ngắn gọn, có dấu đầu dòng. – Armstrongest

+0

Ngay trên. Tôi đã luôn luôn gộp IList và IEnumerable vào cùng một nhóm, nhưng tôi thích ý tưởng này tốt hơn. – scottm

4

chênh lệch HUUUUGGGE. Tôi thấy điều này khá một chút.

Bạn xây dựng một IQueryable trước khi nó truy cập cơ sở dữ liệu. IQueryable chỉ truy cập DB khi hàm eager được gọi (ví dụ .ToList()) hoặc bạn thực sự cố gắng kéo các giá trị ra ngoài. IQueryable = lười biếng.

Một IEnumerable sẽ thực thi lambda của bạn với DB ngay lập tức. IEnumerable = háo hức.

Để sử dụng với mẫu Kho lưu trữ, tôi tin rằng nó háo hức. Tôi thường thấy những người theo đạo luật được thông qua nhưng một người khác sẽ cần phải ủi nó cho bạn. EDIT - Bạn thường thấy IEnumerable thay vì IQueryable vì bạn không muốn các lớp trong kho lưu trữ A) xác định khi nào cơ sở dữ liệu sẽ xảy ra hoặc B) Thêm bất kỳ logic nào vào các kết nối bên ngoài Kho lưu trữ

Có LINQ rất tốt video mà tôi thích - nó đạt được nhiều hơn IEnumerable v IQueryable, nhưng nó thực sự có một số thông tin chi tiết tuyệt vời.

http://channel9.msdn.com/posts/matthijs/LINQ-Tips-Tricks-and-Optimizations-by-Scott-Allen/

+0

Chỉ cần rõ ràng, 'ProductRepository' đang nằm trong ứng dụng của tôi ... trong khi DAL là một dự án riêng biệt mà tôi có tham chiếu đến. Vì vậy, tôi gọi Repository từ ứng dụng của tôi, Repository gọi lớp DBDataContext trong dự án DAL (chứa tất cả các phương thức chung), sau đó thực hiện bất kỳ LinqToSQL nào đối với cơ sở dữ liệu. – Armstrongest

+3

IEnumerable không nhất thiết là háo hức. Enumerable.Select trả về một IEnumerable lười biếng. –

+0

Video tuyệt vời. Cảm ơn vì điều đó! – Armstrongest

3

Bạn có thể sử dụng IQueryable và chấp nhận rằng ai đó có thể tạo một kịch bản có thể xảy ra SELECT N+1. Đây là một bất lợi, cùng với thực tế là bạn có thể kết thúc với mã đó là cụ thể để thực hiện kho lưu trữ của bạn trong các lớp trên kho lưu trữ của bạn. Ưu điểm của điều này là bạn đang cho phép các hoạt động phổ biến ủy nhiệm như phân trang và phân loại được thể hiện bên ngoài của kính gửi của bạn, do đó làm giảm bớt những lo ngại đó. Nó cũng linh hoạt hơn nếu bạn cần nối dữ liệu với các bảng cơ sở dữ liệu khác, vì truy vấn sẽ vẫn là một biểu thức, vì vậy có thể được thêm vào trước khi nó được giải quyết thành truy vấn và truy cập cơ sở dữ liệu.

Cách khác là khóa kho lưu trữ của bạn để nó trả về các danh sách hiện thực hóa bằng cách gọi ToList(). Với ví dụ về phân trang và sắp xếp, bạn sẽ cần phải bỏ qua, bỏ qua và biểu thức sắp xếp làm tham số cho các phương thức của kho lưu trữ của bạn và sử dụng các tham số để chỉ trả về một cửa sổ kết quả. Điều này có nghĩa là kho lưu trữ đang chịu trách nhiệm phân trang và phân loại và tất cả các phép chiếu dữ liệu của bạn.

Đây là một chút của một cuộc gọi phán đoán, bạn có cung cấp cho ứng dụng của bạn sức mạnh của LINQ và ít phức tạp hơn trong kho lưu trữ hay bạn kiểm soát quyền truy cập dữ liệu của mình. Đối với tôi, nó phụ thuộc vào số lượng truy vấn liên quan đến từng thực thể và kết hợp các thực thể và nơi tôi muốn quản lý sự phức tạp đó.

+0

Hmmm ... một số điều cần suy nghĩ. – Armstrongest

6

Một điều nữa cần suy nghĩ: hỗ trợ phân trang/phân loại của bạn ở đâu? Nếu bạn đang cung cấp hỗ trợ phân trang trong kho lưu trữ của mình, hãy trả lại IEnumerable<T> là tốt. Nếu bạn đang phân trang bên ngoài kho lưu trữ của mình (như trong bộ điều khiển hoặc lớp dịch vụ) thì bạn thực sự muốn sử dụng IQueryable<T> vì bạn không muốn tải toàn bộ tập dữ liệu vào bộ nhớ trước khi được phân trang.

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