Получить страницу, содержащую элемент с идентификатором
Использование Entity Framework, если есть MyDbContext с клиентами DbSet.
Я хочу отображать клиентов постранично, поэтому я создал функцию (упрощенно):
public List<Customer> GetCustomerPage<TKey>
(int pageNr, int pageSize, Func<Customer, TKey> keySelector);
Эта функция упорядочивает myDbContext.Customers по keySelector и использует Skip и Take для возврата страницы:
using (MyDbContext myDbContext = ...)
{
return myDbContext.Customers
.Orderby(keySelector)
.Skip(pageNr * pageSize)
.Take(pageSize)
.ToList();
}
Это работает хорошо и эффективно. Теперь предположим, что у меня есть клиент с идентификатором клиента, и мне нужна страница, на которой он находится.
Если бы все было в локальном списке, это было бы легко. Найдите индекс клиента с идентификатором и рассчитайте страницу следующим образом:
int customerIndex = customerList.Single(cust => cust.Id == customerId);
int pageToGet = (int)Math.Floor(customerIndex / pageSize);
Если у вас есть IEnumerable вместо List, вы можете сделать что-то вроде
int customerIndex = Customers.Select( (cust, index) => new
{
Index = index,
Customer = cust,
})
.Single(cust => cust.Id == customerId)
.Index;
Увы, это работает только как AsEnumerable, но не как AsQueryable.
SQL имеет концепцию ROW_NUMBER, и этого было бы достаточно, чтобы получить ROW_NUMBER клиента с customerId.
Несколько вопросов о StackOverFlow отвечают, например, как получить ROW_NUMBER. Как мне перевести запрос, использующий ROW_NUMBER(), в linq?,
Увы, все решения, которые я нахожу, имеют AsEnumerable где-то в операторе LINQ, что вызывает выбор SQL всей коллекции клиентов. Это подтверждается SQL Server Profiler.
Итак вопрос: как получить заказанный номер индекса Клиента с помощью customerId
Кстати: мне это нужно для большинства моих столов. Хранимая процедура для каждой таблицы не может быть хорошим решением.