Сложный алгоритм пейджинга LINQ - PullRequest
2 голосов
/ 01 марта 2011

У нас есть список проектов, которые могут иметь или не иметь коллекцию подпроектов.Наш отчет должен содержать все проекты, кроме тех, которые являются родительским проектом подпроекта.

Мне нужно разбить его на страницы, скажем, по 25 строк.Но если подпроекты появляются на этой странице, тогда ВСЕ подпроекты этого проекта должны появляться на одной странице.Таким образом, при необходимости может появиться более 25 элементов.

Я дошел до

var pagedProjects = db.Projects.Where(x => !x.SubProjects.Any()).Skip(
    (pageNo -1) * pageSize).Take(pageSize);

Очевидно, что это не соответствует второй части требований.

Как еще боль в заднице, мне нужно иметь контроль над пейджером в отчете.Поэтому мне нужно будет рассчитать общее количество страниц.

Я мог бы перебрать всю таблицу проектов, но производительность пострадает.Кто-нибудь может предложить решение с постраничной загрузкой?

РЕДАКТИРОВАТЬ - я, вероятно, должен упомянуть, что SubProjects присоединяется к Projects через внешний ключ с собственной ссылкой, поэтому вся партия, родительские проекты, подпроекты и все возвращается как * 1014.*.

Ответы [ 3 ]

1 голос
/ 01 марта 2011

Мне легче справляться с нумерацией страниц, абстрагируясь от вопроса. Вот источник решения, которое я использую. Это сделает ваш код намного проще и превратит всю логику подкачки в один простой вызов ToPagedList(int index, int pageSize). Я не уверен на 100%, но я полагаю, что первоначально я получил этот источник от проекта Kona Роба Конери (его блог на http://blog.wekeroad.com/).

Класс помощника

public static class Pagination
{
    public static PagedList<T> ToPagedList<T>(this IEnumerable<T> source, int index)
    {
        return new PagedList<T>(source.AsQueryable(), index, 10);
    }
    public static PagedList<T> ToPagedList<T>(this IEnumerable<T> source, int index, int pageSize)
    {
        return new PagedList<T>(source.AsQueryable(), index, pageSize);
    }
    public static PagedList<T> ToPagedList<T>(this IQueryable<T> source, int index, int pageSize)
    {
        return new PagedList<T>(source, index, pageSize);
    }

    public static PagedList<T> ToPagedList<T>(this IQueryable<T> source, int index)
    {
        return new PagedList<T>(source, index, 10);
    }
}

Интерфейсы

public interface IPagedList<T> : IList<T>, IPagedList
{
}
public interface IPagedList
{
    int TotalCount { get; set; }
    int TotalPages { get; set; }
    int PageIndex { get; set; }

    int PageSize { get; set; }

    bool IsPreviousPage { get; }

    bool IsNextPage { get; }
}

Реализация PagedList

public class PagedList<T> : List<T>, IPagedList<T>
{
    public PagedList(IQueryable<T> source, int index, int pageSize)
    {
        int total = source.Count();
        this.TotalCount = total;
        this.TotalPages = total/pageSize;

        if (total%pageSize > 0)
            TotalPages++;

        this.PageSize = pageSize;
        this.PageIndex = index;
        this.AddRange(source.Skip(index*pageSize).Take(pageSize).ToList());
    }

    public PagedList(IEnumerable<T> source, int total, int index, int pageSize)
    {
        this.TotalCount = total;
        this.TotalPages = total/pageSize;

        if (total%pageSize > 0)
            TotalPages++;


        this.PageSize = pageSize;
        this.PageIndex = index;
        this.AddRange(source);
    }

    #region IPagedList<T> Members

    public int TotalPages { get; set; }

    public int TotalCount { get; set; }

    public int PageIndex { get; set; }

    public int PageSize { get; set; }

    public bool IsPreviousPage
    {
        get { return (PageIndex > 0); }
    }

    public bool IsNextPage
    {
        get { return (PageIndex*PageSize) <= TotalCount; }
    }

    #endregion
}
1 голос
/ 01 марта 2011

Возможно, вместо этого попробуйте разбить на страницы родительские проекты, но только с отображением их дочерних элементов.

var pagedParentProjects = db.Projects.Where(x => x.SubProjects.Any()).Skip(pageNo-1) * pageSize).Take(pageSize);

Затем просто прокрутите подпроекты этого проекта при отображении данных.подпроекты с одним и тем же родителем будут на одной странице.

0 голосов
/ 01 марта 2011

Для меня это звучит примерно так:

    var pagedProjects = db.Projects.Skip((pageNo - 1) * pageSize).Take(pageSize);

    var expandedPagedProjects = from p in pagedProjects
                                group p.subprojects by p into grp
                                select grp;

. Это сделает extendedPagedProjects IEnumerable<IGrouping<Project, T>>, где T - это тип вашей коллекции подпроектов (например, List<SubProject>).Таким образом, в основном вы будете разбивать проекты на группы по 25, а затем расширять коллекции подпроектов и группировать их с родительским проектом.Затем вы можете отображать их по своему усмотрению, возможно, просматривая их с помощью вложенного foreach.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...