Vamos imaginar que você possua apenas dois parâmetros de entrada, o indice da página atual e a quantidade de itens que você deseja exibir por página.

Podemos fazer algo bem simples e limpo:

int paginaAtual = 1;
int itensPagina = 15;
 
DataContext db = new DataContext();
 
var resultados = db.Usuarios
                   .Skip((paginaAtual - 1) * itensPagina)
                   .Take(itensPagina);

Observe que como o skip sempre realiza a operação ((paginaAtual - 1) * itensPagina) sempre é pulado exatamente a quantidade de registros anterior a página atual, em seguida apenas obtém os proximos registros de acordo com o parâmetro itensPagina.

Se precisássemos realizar uma ordenação, a mesma seria incluída antes do Skip, como abaixo:

var resultados = db.Usuarios
                   .OrderBy(u => u.nome)
                   .Skip((paginaAtual - 1) * itensPagina)
                   .Take(itensPagina);

Desta forma a paginação sempre será realizada corretamente independente de sua ordenação, pois a mesma é realizada antes da página ser efetuada.

Rafael Zaccanini
MTAC – Microsoft Technical Audience Contributor

Blog: http://www.rafaelzaccanini.net
Twitter: 
@rafaelzaccanini
Facebook: http://www.facebook.com/RafaelZaccaniniNet