web-dev-qa-db-ja.com

LINQ Skip and Takeを使用するPagedList、ただし結果のカウントを使用するページングを表示

CategoryフィルターとItemsPerPageに基づいて、製品のフィルターされたリストを表示しようとしていますが、PagedListで使用しようとすると問題が発生します。

PagedListの専門知識を持っている人は、自分のページネーションコードを書く必要がある場合や、PagedListを使用して必要な結果を取得する方法がある場合、アドバイスをくれます。

現在のページに表示する必要がある行数のみを取得するためにLINQのスキップアンドテイク機能を使用していますが、フィルターの合計数に基づいてページを表示するにはページングリンクが必要です。

例:私の検索フィルターは50の結果を見つけますが、ページごとの行は10項目であるため、LINQのSkip()とTake()を使用して10行のみを取得します。 View.cshtmlにページリンクを表示する必要があります<< 1 | 2 | 3 | 4 | 5 >>デフォルトのPagedListでは、現時点では<< 1> >、1ページしか表示されない理由はわかっていますが、結果のサブセットのみを取得しながら、正しい数のページリンクを表示できるようにする方法を知りたいだけです。

**私の目標は、Webページの応答パフォーマンスが高速になるように、最適化されたクエリをデータベースに書き込むことです。

アクションメソッドのコードは次のようになります。コードは正しい結果を得ていますが、ページネーションは私が必要としているように機能していません:

public ViewResult List(int page =1, string category =null)
{
    if (category != null) this.CurrentCategory = category;

    var products = repository.Products
                    .Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory)
                    .OrderBy(p => p.ProductID)
                    .Skip((page -1) * PageSize)
                    .Take(PageSize);

    return View(products.ToList().ToPagedList(page, PageSize));
}

ページネーションを処理するビューのコードスニペットを次に示します。プロジェクトのGithubサイトを調べましたが、カスタムページを提供するための拡張メソッドが見つかりませんでした。 「ページあたりのアイテム」と@Modelの製品のCount()に基づいてページ数のみをレンダリングすると思います:

@model IPagedList<Product>

//foreach loop that renders the @Model

//Code that displays the pagination using PagedList
<div style="text-align:center">
    @Html.PagedListPager(Model, page => Url.Action("List", new { page = page, category =  ViewBag.CurrentCategory }), PagedListRenderOptions.OnlyShowFivePagesAtATime
    )
</div>
20
badboy11

私はまったく同じ問題を抱えていたため、StaticPagedListを使用することになりました。このようなことができます

public ViewResult List(int page =1, string category =null)
{
    if (category != null) this.CurrentCategory = category;

    var products = repository.Products
                   .Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory)
                   .OrderBy(p => p.ProductID)
                   .Skip((page -1) * PageSize)
                   .Take(PageSize);

var count = repository.Products
                   .Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory).Count();

var resultAsPagedList = new StaticPagedList<Product>(products, page, PageSize, count);

    return View(resultAsPagedList);
}

ビューについては、モデルタイプを置き換えるだけです

@model StaticPagedList<Product>
24
mpricochi

ToPagedListTakeSkipを内部で使用し、IQueryable<T>クラスの拡張を使用すると、必要なデータベースクエリが生成されます。また、TotalItemCountをメタデータに取得します。

Sqlに変換できないメソッドを使用しているため、クエリ結果をメモリに取り込む必要がある場合があります。つまり、PagedListEnumerableに戻す必要があります。この問題を回避するには、次のようなStaticPagedListメソッドを使用します。

   var superset= repository.Products
      .Where(p => this.CurrentCategory == null 
             || p.Category == this.CurrentCategory)
      .OrderBy(p => p.ProductID)
      .ToPagedList(page, PageSize);

   var subset = superset
      .AsEnumerable()
      .Select(p => new ProductViewModel
      {
          OtherData = p.UntranslateableMethod()  
      })

    var model = new StaticPagedList<ProductViewModel>(subset,
       superset.GetMetaData());
}

コメントのメソッドの要約から:

すでに分割されたサブセットと、スーパーセットのサイズとその中のサブセットの位置に関する情報を含むPagedList.StaticPagedListクラスの新しいインスタンスを初期化します。

3
Colin

それでも、カウントを個別に要求する必要があります。

var products = repository.Products
                         .Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory);
var numProds = products.Count();
var mypage = products.OrderBy(p => p.ProductID)
                     .Skip((page -1) * PageSize)
                     .Take(PageSize);
2
Michael Dunlap

PagedListのメソッドを使用する場合、LINQ .skip()および.take()も使用する必要はありません。そうすると、リストを事前に制限していることになり、ライブラリを使用しても意味がありません。最初にリストをフィルタリングして.skip().take()は、それらのpagesizeの結果を再度フィルター処理してpagesizeに渡します。これはもちろん同じですが、PagedListは合計がわからないのです。

すべての結果をロードしないようにする場合は、IQueryableまたはEnumerableではなく、ListをPagedListに送信するだけです。 PagedListは.Skip().Take()を追加し、データベースはそれらの結果のみを返します。

2
solidau

上記の説明は正しいです。ただし、静的選択リストを割り当てる場合は..

new StaticPagedList<Product>(products, page, PageSize, count);.

実際のカウントから表示されるページリンクの数が少なくなります。カウントが10の場合、ページサイズが5であれば2ページのみが表示されます。

すべてのページリンクをカウントして表示する場合は、

pass count*5 ie count*pagesize

new StaticPagedList<Product>(products, page, PageSize, count*5);//in my case page size is 5

または新しいStaticPagedList(products、page、PageSize、count * pagesize);

したがって、使用可能なすべてのカウントをページで提供します。

0
Abhi