2010-08-09 25 views
10

Điều gì có thể gây ra sự cố này?Phương thức 'Bỏ qua' chỉ được hỗ trợ cho đầu vào được sắp xếp trong LINQ to Entities

public ActionResult Index(int page = 0) 
{ 
    const int pageSize = 3; 
    var areas = repo.FindAllAreas(); 
    var paginatedArea = new PaginatedList<Area>(areas, page, pageSize); 

    return View(paginatedArea); 
} 


using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace UTEPSA.Controllers 
{ 
    class PaginatedList<T> : List<T> 
    { 
     public int PageIndex { get; private set; } 
     public int PageSize { get; private set; } 
     public int TotalCount { get; private set; } 
     public int TotalPages { get; private set; } 
     public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize) 
     { 
      PageIndex = pageIndex; 
      PageSize = pageSize; 
      TotalCount = source.Count(); 
      TotalPages = (int)Math.Ceiling(TotalCount/(double)PageSize); 
//ERROR HERE->>this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize)); 
     } 
     public bool HasPreviousPage 
     { 
      get 
      { 
       return (PageIndex > 0); 
      } 
     } 
     public bool HasNextPage 
     { 
      get 
      { 
       return (PageIndex + 1 < TotalPages); 
      } 
     } 
    } 
} 

Mọi đề xuất?

+0

Bạn đã xem thư viện mvccontrib chưa? Nó chứa một thành phần phân trang: http://www.jeremyskinner.co.uk/2010/03/14/mvccontrib-grid-part-6-sorting/. Không chắc chắn làm thế nào nó tiếp cận vấn đề này mặc dù ... – jeroenh

Trả lời

17

Dường như lỗi chính xác là những gì được nói. "Bỏ qua chỉ được cho phép trên đầu vào Sắp xếp". Đang tìm kiếm các lỗi này, tôi đã tìm thấy này:

http://weblogs.asp.net/rajbk/archive/2009/09.aspx

Nó cần được cố định nếu bạn bao gồm một OrderBy trước Skip:

source.orderBy(???).Skip(PageIndex * PageSize).Take(PageSize)); 

nào có thể là một vấn đề vì bạn đang đi qua một generic đối tượng T. Bạn có thể cần phải mở rộng lớp của bạn để nhận một tham số khác để chỉ ra thứ tự theo phần tử.

Tôi hy vọng điều này sẽ hữu ích.

+0

Từ bài viết: Vấn đề này dường như đã được cố định trong khuôn khổ .NET 4.0 [cho linq-to-sql, không linq-to-thực thể] ... – jeroenh

+0

Không chọn thuộc tính cho cơ sở orderby trên đó nếu nó không thể thực hiện được! vì phân trang của bạn không hoạt động chính xác. – Elnaz

0

An IQueryable không có đơn đặt hàng, vì vậy hãy nói "bỏ qua các yếu tố tiếp theo x" không có ý nghĩa gì.

Nếu bạn bao gồm một order by khoản (hoặc có thể là một AsEnumerable() cuộc gọi - chưa được kiểm tra) sau đó dữ liệu của bạn có một trật tự và SkipTake hiện nay có hợp lý.

+5

Bạn không muốn thêm AsEnumerable. Điều này sẽ đánh bại lý do chính của phân trang mà là để chỉ lấy một số lượng hạn chế của dữ liệu từ cơ sở dữ liệu ... Thêm AsEnumerable() sẽ kéo trong tất cả mọi thứ, và áp dụng phân trang trong bộ nhớ. – jeroenh

+1

Bạn đã thử nghiệm điều này (hoặc có nguồn), hay bạn đang giả định nó? Gọi ToList hoặc ToArray chắc chắn sẽ kéo vào mọi thứ, nhưng không có gì trong hợp đồng của AsEnumerable buộc nó phải lấy tất cả dữ liệu trước khi trả về các phần tử đầu tiên (và tiếp theo). – Zooba

+2

Chạy .Skip() và .Take() trên IEnumerable sẽ dẫn đến truy vấn trả về TẤT CẢ các kết quả từ cơ sở dữ liệu khi .ToList() được gọi. Trong tình huống đó, việc phân trang thực tế được thực hiện trong bộ nhớ. Tôi đã thử nghiệm điều này bằng cách sử dụng SQL Server Profiler và truy vấn sql được tạo ra không có bất kỳ hạn chế phân trang nào. – quakkels

1

được làm việc (sử dụng IOrderedQueryable đầu tiên):

http://msdn.microsoft.com/en-us/library/bb738702.aspx

IOrderedQueryable<Product> products = context.Products 
     .OrderBy(p => p.ListPrice); 

IQueryable<Product> allButFirst3Products = products.Skip(3); 

Console.WriteLine("All but first 3 products:"); 
foreach (Product product in allButFirst3Products) 
{ 
    Console.WriteLine("Name: {0} \t ID: {1}", 
     product.Name, 
     product.ProductID); 
} 
1

tôi muốn xác nhận điều này bằng cách chạy tương đương với SQL của một LINQ tương tự skip/mất truy vấn.

SELECT * FROM [table] 
--order by [column] //omitted! 
OFFSET 10 ROWS 
FETCH NEXT 15 rows only 

Lưu ý rằng khi lệnh quy định tại khoản được bỏ qua, lỗi SQL là ít hơn nhiều thông tin:

"Invalid usage of the option NEXT in the FETCH statement." 

Vì vậy, các "đầu vào sắp xếp" là thực sự cần thiết trên cơ sở dữ liệu cấp. Kudos cho LINQ để giúp các nhà phát triển viết các câu lệnh SQL nâng cao!

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