Получить страницу, содержащую элемент с идентификатором

Использование 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

Кстати: мне это нужно для большинства моих столов. Хранимая процедура для каждой таблицы не может быть хорошим решением.

0 ответов

Другие вопросы по тегам