Get page containing an item with an Id

时间:2016-04-07 10:33:01

标签: c# entity-framework linq row-number

Using Entity Framework if have a MyDbContext with a DbSet Customers.

I want to display the customers page by page, so I have created a function (simplified):

public List<Customer> GetCustomerPage<TKey>
    (int pageNr, int pageSize, Func<Customer, TKey> keySelector);

This function will order myDbContext.Customers by keySelector, and use Skip and Take to return a page:

using (MyDbContext myDbContext = ...)
{
    return myDbContext.Customers
        .Orderby(keySelector)
        .Skip(pageNr * pageSize)
        .Take(pageSize)
        .ToList();
}

This works fine and efficient. Now suppose I have a customer with a customerId and I want the page on which this customer is.

If everything would be in a local List, then this would be easy. Find the index of the customer with Id, and calculate the page as follows:

int customerIndex = customerList.Single(cust => cust.Id == customerId);
int pageToGet = (int)Math.Floor(customerIndex / pageSize);

If you have an IEnumerable instead of a List you could do something like

int customerIndex = Customers.Select( (cust, index) => new
    {
        Index = index,
        Customer = cust,
    })
    .Single(cust => cust.Id == customerId)
    .Index;

Alas, this works only AsEnumerable, not AsQueryable.

SQL has the concept of ROW_NUMBER, and it would enough to get the ROW_NUMBER of the customer with customerId.

Several questions on StackOverFlow answer how to get the ROW_NUMBER, for instance How do I translate a query that uses ROW_NUMBER() into linq?.

Alas, all solutions I find have AsEnumerable somewhere in the LINQ statement, which causes an SQL select of the complete customer collection. This is confirmed by the SQL Server Profiler.

So question: how to get the ordered index number of the Customer with customerId

By the way: I need this for most of my tables. A stored procedure for every table might not be a good solution.

0 个答案:

没有答案