web-dev-qa-db-ja.com

メソッド 'Skip'は、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);
            }
        }
    }
}

助言がありますか?

19
Sergio Tapia

エラーはまさにそれが言っていることのようです。 「スキップはソートされた入力でのみ許可されています」。このエラーを検索しています これを見つけました

Skipの前にOrderByを含めると、修正されるはずです。

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

ジェネリックオブジェクトTを渡すので、これは問題になる可能性があります。要素による順序を示す別のパラメーターを受け取るには、クラスを拡張する必要がある場合があります。

26
Wagner Silveira

これは機能します(最初のIOrderedQueryableを使用):

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);
}
3
mavore

同様のLINQスキップ/テイククエリに相当するSQLを実行してこれを検証したかったのです。

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

Order-by句を省略した場合、SQLエラーの情報ははるかに少なくなります。

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

したがって、「ソートされた入力」は実際にはデータベースレベルで必要です。開発者が高度なSQLステートメントを作成するのを支援するLINQへの称賛!

2
Peter Shen

IQueryableには順序がないため、「次のx要素を無視する」と言っても意味がありません。

_order by_句(またはAsEnumerable()呼び出し-nested)を含めると、データはSkipTakeが賢明になりました。

1
Zooba