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.