web-dev-qa-db-fra.com

PagedList utilisant LINQ Skip and Take, mais affiche la pagination à l'aide de Count of results

J'essaie d'afficher une liste filtrée de produits, basée sur le filtre de catégorie et ItemsPerPage, mais j'ai des problèmes lorsque j'essaie de l'utiliser avec PagedList.

Une personne possédant l'expertise de PagedList pourrait me conseiller si j'ai besoin d'écrire mon propre code de pagination ou s'il existe un moyen d'obtenir les résultats dont j'ai besoin en utilisant PagedList.

J'utilise les fonctions Skip & Take de LINQ pour obtenir uniquement le nombre de lignes qui doivent être affichées sur la page actuelle, mais j'aimerais quand même que les liens de pagination affichent les pages en fonction du nombre total de filtres.

Par exemple :: mon filtre de recherche trouve 50 résultats, mais comme mes lignes par page représentent 10 éléments, j'utilise Skip () & Take () de LINQ pour récupérer seulement 10 lignes. J'ai encore besoin d'afficher dans mon View.cshtml les liens de la page << 1 | 2 | 3 | 4 | 5 >> En ce moment avec la PagedList par défaut, je ne reçois que << 1> >, je sais pourquoi je ne vois qu'une seule page mais je voulais juste savoir comment le faire fonctionner pour afficher le nombre correct de liens de page, tout en n'obtenant qu'un sous-ensemble de résultats.

** Mon objectif est d'écrire des requêtes optimisées dans la base de données afin que les performances de réponse des pages Web soient rapides.

Voici à quoi ressemble mon code pour la méthode d'action. Le code obtient les résultats corrects mais la pagination ne fonctionne pas car j'ai besoin que ce soit:

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

Voici l'extrait de code de la vue qui traite de la pagination. J'ai regardé le site Github du projet mais je n'ai pas trouvé de méthode d'extension pour fournir des pages personnalisées. Je pense qu'il ne rendra que le nombre de pages en fonction des "articles par page" et du nombre () de produits dans le @Model:

@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

J'ai eu exactement le même problème et j'ai fini par utiliser StaticPagedList. Vous pouvez faire quelque chose comme ça

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

quant à la vue, il suffit de remplacer le type de modèle

@model StaticPagedList<Product>
24
mpricochi

ToPagedList utilise Take et Skip en interne et lorsque vous utilisez l'extension à IQueryable<T> classe, qui entraînera la requête de base de données dont vous avez besoin. Il récupère également le TotalItemCount dans ses métadonnées.

Parfois, vous devrez peut-être mettre les résultats de la requête en mémoire car vous utilisez une méthode qui ne peut pas être traduite en SQL. Cela signifie que vous devez reconvertir le PagedList en Enumerable. Vous pouvez contourner ce problème en utilisant la méthode StaticPagedList comme ceci:

   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());
}

Du résumé de la méthode dans les commentaires:

Initialise une nouvelle instance de la classe PagedList.StaticPagedList qui contient le sous-ensemble déjà divisé et des informations sur la taille du sur-ensemble et la position du sous-ensemble à l'intérieur.

3
Colin

Vous devrez probablement demander un décompte séparément.

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

Si vous utilisez les méthodes de PagedList, vous n'avez pas besoin d'utiliser également LINQ .skip() et .take(). Si vous le faites, alors vous pré-limitez la liste, et il serait inutile d'utiliser la bibliothèque car vous filtrez d'abord la liste pour obtenir pagesize résultats par .skip() et .take() puis en passant ces pagesize résultats à filtrer à nouveau vers pagesize, ce qui sera bien sûr le même, mais alors PagedList ne sait pas quel est le total.

Si vous voulez vous assurer que vous ne chargez pas tous les résultats, envoyez simplement un IQueryable à PagedList au lieu d'un Enumerable ou List. PagedList ajoutera la .Skip() et .Take() pour vous, et votre base de données ne renverra que ces résultats.

2
solidau

L'explication ci-dessus est correcte. Mais lorsque vous attribuez une liste de sélection statique.

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

Il affiche moins de liens de page par rapport au nombre réel. Si le nombre est de 10, il n'affiche que 2 pages si la taille de votre page est de 5.

Si vous souhaitez afficher toutes les pages de liens disponibles en nombre, alors

pass count*5 ie count*pagesize

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

ou nouvelle StaticPagedList (produits, page, PageSize, count * pagesize);

ainsi, il fournit tous les comptes disponibles dans les pages.

0
Abhi