Question

Je suis déconcerté par ce problème de données facile.

J'utilise Entity Framework et une base de données de produits. Ma page de résultats renvoie une liste paginée de ces produits. En ce moment, mes résultats sont triés par le nombre de ventes de chaque produit, de sorte que mon code ressemble à ceci:

return Products.OrderByDescending(u => u.Sales.Count());

renvoie un ensemble de données IQueryable de mes entités, triées par le nombre de ventes.

Je veux que ma page de résultats pour montrer le rang de chaque produit (dans l'ensemble de données). Mes résultats devraient ressembler à ceci:

Page #1
1. Bananas
2. Apples
3. Coffee

Page #2
4. Cookies
5. Ice Cream
6. Lettuce

J'attends que je veux juste ajouter une colonne dans mes résultats en utilisant la variable SQL ROW_NUMBER ... mais je ne sais pas comment ajouter cette colonne à mes résultats datatable.

Ma page résultante contient une boucle foreach, mais depuis que je suis sur un ensemble paginé je devine en utilisant ce numéro de simuler un numéro de classement ne serait pas la meilleure approche.

Alors, ma question est, comment puis-je ajouter une colonne ROW_NUMBER à mes résultats de la requête dans ce cas?

Pas de solution correcte

Autres conseils

Utilisez le de surcharge indexée de Select :

var start = page * rowsPerPage;
Products.OrderByDescending(u => u.Sales.Count())
    .Skip(start)
    .Take(rowsPerPage)
    .AsEnumerable()
    .Select((u, index) => new { Product = u, Index = index + start });

En fait, à l'aide OrderBy puis + Sauter Take génère ROW_NUMBER dans EF 4.5 (vous pouvez vérifier avec SQL Profiler).

Je cherchais un moyen de faire la même chose que vous demandez et je suis en mesure d'obtenir ce que je dois par une simplification de la réponse de Craig:

var start = page * rowsPerPage;
Products.OrderByDescending(u => u.Sales.Count())
    .Skip(start)
    .Take(rowsPerPage)
    .ToList();

Par ailleurs, le SQL généré utilise ROW_NUMBER> début et TOP rowsPerPage.

Voici une réponse longue haleine. Tout d'abord créer une classe pour loger le nombre de paires / article comme ceci:

public class NumberedItem<T>
{
    public readonly int Number;
    public readonly T Item;

    public NumberedItem(int number, T item)
    {
        Item = item;
        Number = number;
    }
}

Vient ensuite une abstraction autour d'une page d'articles (numérotée ou non):

class PageOf<T> : IEnumerable<T>
{
    private readonly int startsAt;
    private IEnumerable<T> items;

    public PageOf(int startsAt, IEnumerable<T> items)
    {
        this.startsAt = startsAt;
        this.items = items;
    }

    public IEnumerable<NumberedItem<T>> NumberedItems
    {
        get
        {
            int index = 0;
            foreach (var item in items)
                yield return new NumberedItem<T>(startsAt + index++, item);
            yield break;
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach (var item in items)
            yield return item;
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

Une fois que vous avez que vous pouvez « Paginate » une collection interrogeable particulier en utilisant ceci:

class PaginatedQueryable<T>
{
    private readonly int PageSize;
    private readonly IQueryable<T> Source;

    public PaginatedQueryable(int PageSize, IQueryable<T> Source)
    {
        this.PageSize = PageSize;
        this.Source = Source;
    }

    public PageOf<T> Page(int pageNum)
    {
        var start = (pageNum - 1) * PageSize;
        return new PageOf<T>(start + 1, Source.Skip(start).Take(PageSize));
    }
}

Et enfin une belle méthode d'extension pour couvrir le laid:

static class PaginationExtension
{
    public static PaginatedQueryable<T> InPagesOf<T>(this IQueryable<T> target, int PageSize)
    {
        return new PaginatedQueryable<T>(PageSize, target);
    }
}

vous pouvez maintenant faire ce qui signifie:

var products = Products.OrderByDescending(u => u.Sales.Count()).InPagesOf(20).Page(1);

foreach (var product in products.NumberedItems)
{
    Console.WriteLine("{0} {1}", product.Number, product.Item);
}

Essayer cette

var x = Products.OrderByDecending(u => u.Sales.Count());
var y = x.ToList();

for(int i = 0; i < y.Count; i++) {
    int myNumber = i; // this is your order number
}

Tant que la liste reste dans le même ordre, ce qui devrait se produire à moins que le nombre de ventes change. Vous pourriez être en mesure d'obtenir un décompte précis;

Il y a aussi cette façon de le faire.

var page = 2;
var count = 10;
var startIndex = page * count;

var x = Products.OrderByDecending(u => u.Sales.Count());
var y = x.Skip(startIndex).Take(count);

Cela donne l'index de départ pour la page, plus il vous donne un petit ensemble de ventes pour afficher sur la page. Vous venez de commencer le comptage sur votre site Web startIndex.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top