
Paginazione con Linq
In .NET 10 è possibile gestire la paginazione e l'ordinamento dinamico di collection in memoria (anche lette da Database) con un semplice extension method:
l'extension method PagingAndSorting va usato in questo modo:
posso anche filtrare con Where:
C#
using System.Linq.Dynamic.Core;
public static class IQueryableExtension
{
/// <summary>
/// es,: GET https://localhost:7182/api/test?page=1&size=5&orderBy=idcLiente&direction=desch
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="page">pagina iniziale parte da 1</param>
/// <param name="size">dimensione pagina</param>
/// <param name="validSortColumns">colonne valide per il sort, la prima è il default ASC se non c'è match</param>
/// <param name="orderBy">nome colonna case insensitive</param>
/// <param name="direction">ASC | DESC</param>
/// <param name=""></param>
/// <returns></returns>
public static IQueryable<T> PagingAndSorting<T>(this IEnumerable<T> source, int page, int size, string[]? validSortColumns = null, string? orderBy = null, string? direction = null)
{
if (page < 1) page = 1;
if (size > 5000) size = 5000;
else if (size < 1) size = 1;
var query = source.AsQueryable();
if (validSortColumns != null && validSortColumns.Length > 0 && !string.IsNullOrWhiteSpace(orderBy))
{
bool descending = direction?.Equals("desc", StringComparison.OrdinalIgnoreCase) ?? false;
if (!validSortColumns.Contains(orderBy, StringComparer.OrdinalIgnoreCase))
{
// setto la prima colonna come default asc
orderBy = validSortColumns[0];
descending = false;
}
query = query.OrderBy(orderBy + (descending ? " DESC" : " ASC"));
}
return query
.Skip((page - 1) * size)
.Take(size);
}
}
C#
static string[] validSortColumns = ["IDCliente", "Nome", "Cognome", "Email", "Genere", "Eta", "Citta", "DataIscrizione", "TotaleSpeso", "NumeroOrdini", "StatoAccount"];
[HttpGet("")]
public object GetAll(int page, int size = 25, string? orderBy = null, string? direction = null)
{
List<TestItem> item = JsonSerializer.Deserialize<List<TestItem>>(DATASET, jsonOptions) ?? [];
return item.PagingAndSorting<TestItem>(page, size, validSortColumns, orderBy, direction);
}
const string DATASET = """
[
{ "idCliente": 1, "nome": "Alessandro", "cognome": "Rossi", "Email": "alessandro.rossi.1@example.com", "Genere": "M", "Eta": 42, "Citta": "Milano", "dataIscrizione": "2023-01-15", "totaleSpeso": 1250.45, "numeroOrdini": 12, "statoAccount": "Attivo" },
{ "idCliente": 2, "nome": "Giulia", "cognome": "Bianchi", "Email": "giulia.bianchi.2@example.com", "Genere": "F", "Eta": 31, "Citta": "Roma", "dataIscrizione": "2023-02-18", "totaleSpeso": 450.20, "numeroOrdini": 5, "statoAccount": "Attivo" },
...
]
""";
private readonly JsonSerializerOptions jsonOptions = new() { PropertyNameCaseInsensitive = true };
internal record TestItem
{
public int IDCliente { get; set; }
public string Nome { get; set; } = string.Empty;
public string Cognome { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public char Genere { get; set; }
public int Eta { get; set; }
public string Citta { get; set; } = string.Empty;
public DateTime DataIscrizione { get; set; }
public double TotaleSpeso { get; set; }
public int NumeroOrdini { get; set; }
public string StatoAccount { get; set; } = string.Empty;
}
C#
[HttpGet("")]
public object GetAll(int page, int size = 25, string? orderBy = null, string? direction = null)
{
List<TestItem> item = JsonSerializer.Deserialize<List<TestItem>>(DATASET, jsonOptions) ?? [];
return item
.Where(x => string.IsNullOrWhiteSpace(x.Email) == false)
.PagingAndSorting<TestItem>(page, size, validSortColumns, orderBy, direction);
}
ATTENZIONE: molto importante, da usare con solo con piccole collection/dataset di poche centinaia di righe.
Per grosse tabelle con migliaia o più righe, meglio gestire la paginazione lato Database, vedi Paginazione in T-SQL con SQL Server 2012.
Per grosse tabelle con migliaia o più righe, meglio gestire la paginazione lato Database, vedi Paginazione in T-SQL con SQL Server 2012.