标签云

用LINQ分页采集

How do you page through a collection in LINQ given that you have a startIndex and a count?

2016年12月08日46分13秒

A few months back I wrote a blog post about Fluent Interfaces and LINQ which used an Extension Method on IQueryable<T> and another class to provide the following natural way of paginating a LINQ collection.

var query = from i in ideas
            select i;
var pagedCollection = query.InPagesOf(10);
var pageOfIdeas = pagedCollection.Page(2);

You can get the code from the MSDN Code Gallery Page: Pipelines, Filters, Fluent API and LINQ to SQL.

2016年12月07日46分13秒

It is very simple with the Skip and Take extension methods.

var query = from i in ideas
            select i;

var paggedCollection = query.Skip(startIndex).Take(count);

2016年12月07日46分13秒

I solved this a bit differently than what the others have as I had to make my own paginator, with a repeater. So I first made a collection of page numbers for the collection of items that I have:

// assumes that the item collection is "myItems"

int pageCount = (myItems.Count + PageSize - 1) / PageSize;

IEnumerable<int> pageRange = Enumerable.Range(1, pageCount);
   // pageRange contains [1, 2, ... , pageCount]

Using this I could easily partition the item collection into a collection of "pages". A page in this case is just a collection of items (IEnumerable<Item>). This is how you can do it using Skip and Take together with selecting the index from the pageRange created above:

IEnumerable<IEnumerable<Item>> pageRange
    .Select((page, index) => 
        myItems
            .Skip(index*PageSize)
            .Take(PageSize));

Of course you have to handle each page as an additional collection but e.g. if you're nesting repeaters then this is actually easy to handle.


The one-liner TLDR version would be this:

var pages = Enumerable
    .Range(0, pageCount)
    .Select((index) => myItems.Skip(index*PageSize).Take(PageSize));

Which can be used as this:

for (Enumerable<Item> page : pages) 
{
    // handle page

    for (Item item : page) 
    {
        // handle item in page
    }
}

2016年12月07日46分13秒

This question is somewhat old, but I wanted to post my paging algorithm that shows the whole procedure (including user interaction).

const int pageSize = 10;
const int count = 100;
const int startIndex = 20;

int took = 0;
bool getNextPage;
var page = ideas.Skip(startIndex);

do
{
    Console.WriteLine("Page {0}:", (took / pageSize) + 1);
    foreach (var idea in page.Take(pageSize))
    {
        Console.WriteLine(idea);
    }

    took += pageSize;
    Console.WriteLine("Next page (y/n)?");
    char answer = Console.ReadLine().FirstOrDefault();
    getNextPage = default(char) != answer && 'y' == char.ToLowerInvariant(answer);

    if (getNextPage)
    {
        page = page.Skip(pageSize);
    }
}
while (getNextPage && took < count);

2016年12月07日46分13秒