120 Stimmen

Paging mit LINQ für Objekte

Wie würden Sie Paging in einer LINQ-Abfrage implementieren? Im Moment würde es mir genügen, wenn die Funktion sql TOP nachgeahmt werden könnte. Ich bin mir jedoch sicher, dass der Bedarf an einer vollständigen Unterstützung für das Paging früher oder später ohnehin auftritt.

var queryResult = from o in objects
                  where ...
                  select new
                      {
                         A = o.a,
                         B = o.b
                      }
                   ????????? TOP 10????????

5voto

Jack Marchetti Punkte 15256

EDIT - Skip(0) wurde entfernt, da es nicht notwendig ist.

var queryResult = (from o in objects where ...
                      select new
                      {
                          A = o.a,
                          B = o.b
                      }
                  ).Take(10);

2 Stimmen

Sollten Sie nicht die Reihenfolge der Take/Skip-Methoden ändern? Skip(0) nach Take macht keinen Sinn. Vielen Dank für das Beispiel im Abfragestil.

3 Stimmen

Nein, er hat Recht. Take 10, Skip 0 nimmt die ersten 10 Elemente. Skip 0 ist sinnlos und sollte niemals durchgeführt werden. Und die Reihenfolge der Take y Skip Angelegenheiten -- Skip 10, Take 10 nimmt die Elemente 10-20; Take 10, Skip 10 liefert keine Elemente.

0 Stimmen

Möglicherweise benötigen Sie auch Klammern um die Abfrage, bevor Sie Take aufrufen. (from ... select ...).Take(10). Ich habe das Konstrukt mit der Auswahl einer Zeichenkette aufgerufen. Ohne Klammern gab Take die ersten 10 Zeichen der Zeichenkette zurück, anstatt das Abfrageergebnis einzuschränken :)

4voto

Michael Freidgeim Punkte 23629

Ähnlich wie Antwort von Lukazoid Ich habe eine Erweiterung für IQueryable erstellt.

   public static IEnumerable<IEnumerable<T>> PageIterator<T>(this IQueryable<T> source, int pageSize)
            {
                Contract.Requires(source != null);
                Contract.Requires(pageSize > 0);
                Contract.Ensures(Contract.Result<IEnumerable<IQueryable<T>>>() != null);

                using (var enumerator = source.GetEnumerator())
                {
                    while (enumerator.MoveNext())
                    {
                        var currentPage = new List<T>(pageSize)
                        {
                            enumerator.Current
                        };

                        while (currentPage.Count < pageSize && enumerator.MoveNext())
                        {
                            currentPage.Add(enumerator.Current);
                        }
                        yield return new ReadOnlyCollection<T>(currentPage);
                    }
                }
            }

Sie ist nützlich, wenn Skip oder Take nicht unterstützt werden.

3voto

Todd A. Stedel Punkte 116
var pages = items.Select((item, index) => new { item, Page = index / batchSize }).GroupBy(g => g.Page);

Batchsize ist natürlich eine ganze Zahl. Dies macht sich die Tatsache zunutze, dass ganze Zahlen einfach keine Nachkommastellen haben.

Diese Antwort ist halb im Scherz gemeint, aber sie wird das tun, was Sie wollen, und weil sie zeitversetzt ist, werden Sie keine großen Leistungseinbußen erleiden, wenn Sie das tun

pages.First(p => p.Key == thePage)

Diese Lösung ist nicht für LinqToEntities, ich weiß nicht einmal, ob es dies in eine gute Abfrage machen könnte.

1voto

Randy Punkte 21

Ich verwende diese Erweiterungsmethode:

public static IQueryable<T> Page<T, TResult>(this IQueryable<T> obj, int page, int pageSize, System.Linq.Expressions.Expression<Func<T, TResult>> keySelector, bool asc, out int rowsCount)
{
    rowsCount = obj.Count();
    int innerRows = rowsCount - (page * pageSize);
    if (innerRows < 0)
    {
        innerRows = 0;
    }
    if (asc)
        return obj.OrderByDescending(keySelector).Take(innerRows).OrderBy(keySelector).Take(pageSize).AsQueryable();
    else
        return obj.OrderBy(keySelector).Take(innerRows).OrderByDescending(keySelector).Take(pageSize).AsQueryable();
}

public IEnumerable<Data> GetAll(int RowIndex, int PageSize, string SortExpression)
{
    int totalRows;
    int pageIndex = RowIndex / PageSize;

    List<Data> data= new List<Data>();
    IEnumerable<Data> dataPage;

    bool asc = !SortExpression.Contains("DESC");
    switch (SortExpression.Split(' ')[0])
    {
        case "ColumnName":
            dataPage = DataContext.Data.Page(pageIndex, PageSize, p => p.ColumnName, asc, out totalRows);
            break;
        default:
            dataPage = DataContext.vwClientDetails1s.Page(pageIndex, PageSize, p => p.IdColumn, asc, out totalRows);
            break;
    }

    foreach (var d in dataPage)
    {
        clients.Add(d);
    }

    return data;
}
public int CountAll()
{
    return DataContext.Data.Count();
}

1voto

Alen.Toma Punkte 4903
    public LightDataTable PagerSelection(int pageNumber, int setsPerPage, Func<LightDataRow, bool> prection = null)
    {
        this.setsPerPage = setsPerPage;
        this.pageNumber = pageNumber > 0 ? pageNumber - 1 : pageNumber;
        if (!ValidatePagerByPageNumber(pageNumber))
            return this;

        var rowList = rows.Cast<LightDataRow>();
        if (prection != null)
            rowList = rows.Where(prection).ToList();

        if (!rowList.Any())
            return new LightDataTable() { TablePrimaryKey = this.tablePrimaryKey };
        //if (rowList.Count() < (pageNumber * setsPerPage))
        //    return new LightDataTable(new LightDataRowCollection(rowList)) { TablePrimaryKey = this.tablePrimaryKey };

        return new LightDataTable(new LightDataRowCollection(rowList.Skip(this.pageNumber * setsPerPage).Take(setsPerPage).ToList())) { TablePrimaryKey = this.tablePrimaryKey };
  }

Das habe ich getan. Normalerweise beginnt man bei 1, aber in IList beginnt man mit 0. Also, wenn Sie 152 Zeilen haben, die bedeuten, dass Sie 8 paging haben, aber in IList haben Sie nur 7. Ich hoffe das macht die Sache für dich klar

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X