Oldalszámozás

A lapozás az eredmények lapokban való lekérésére utal, nem pedig egyszerre; ez általában nagy eredményhalmazok esetében történik, ahol megjelenik egy felhasználói felület, amely lehetővé teszi a felhasználó számára az eredmények következő vagy előző oldalára való navigálást.

Figyelmeztetés

A használt lapozási módszertől függetlenül mindig győződjön meg arról, hogy a rendelés teljesen egyedi. Ha például az eredmények csak dátum szerint vannak rendezve, de több találat is lehet ugyanazzal a dátummal, akkor az eredmények kihagyhatók a lapozáskor, mivel két lapozó lekérdezésben eltérő sorrendben vannak rendezve. A dátum és az azonosító (vagy bármely más egyedi tulajdonság vagy tulajdonságok kombinációja) alapján történő megrendelés teljesen egyedivé teszi a rendelést, és elkerüli ezt a problémát. Vegye figyelembe, hogy a relációs adatbázisok alapértelmezés szerint nem alkalmaznak sorrendet, még az elsődleges kulcson sem.

Megjegyzés:

Az Azure Cosmos DB saját lapozási mechanizmussal rendelkezik, lásd a dedikált dokumentációs oldalt.

Eltolásos oldalszámozás

Az adatbázisokkal való lapozás megvalósításának gyakori módja a Skip és Take LINQ operátorok használata, valamint azok OFFSET és LIMIT megfelelői az SQL-ben. A 10 találatos oldalméret miatt a harmadik oldal lekérhető az EF Core-jal az alábbiak szerint:

var position = 20;
var nextPage = await context.Posts
    .OrderBy(b => b.PostId)
    .Skip(position)
    .Take(10)
    .ToListAsync();

Sajnos, bár ez a technika nagyon intuitív, súlyos hiányosságokat is tapasztal:

  1. Az adatbázisnak továbbra is feldolgoznia kell az első 20 bejegyzést, még akkor is, ha azok nem kerülnek vissza az alkalmazásba; ez valószínűleg jelentős számítási terhelést okoz, amely a kihagyott sorok számával együtt nő.
  2. Ha a frissítések egyidejűleg történnek, előfordulhat, hogy a lapozás bizonyos bejegyzéseket kihagy, vagy kétszer jeleníti meg őket. Ha például a felhasználó a 2. oldalról a 3. oldalra való áttéréskor eltávolít egy bejegyzést, a teljes eredményhalmaz "felfelé" vált, és egy bejegyzést kihagy.

Kulcskészlet alapú lapozás

Az eltolásalapú lapozás ajánlott alternatívája – más néven kulcskészlet-lapozás vagy keresőalapú lapozás – az, hogy egyszerűen egy WHERE záradékot használjon a sorok közvetlen kihagyására eltolás helyett. Ez azt jelenti, hogy az utolsó beolvasott bejegyzés releváns értékeit (az eltolás helyett) jegyezze fel, és kérje meg a következő sorokat a sor után. Ha például az utolsó beolvasott lap utolsó bejegyzése 55-ös azonosítóval rendelkezik, egyszerűen a következőket tennénk:

var lastId = 55;
var nextPage = await context.Posts
    .OrderBy(b => b.PostId)
    .Where(b => b.PostId > lastId)
    .Take(10)
    .ToListAsync();

Feltételezve, hogy egy index definiálva PostIdvan, ez a lekérdezés nagyon hatékony, és nem érzékeny az alacsonyabb azonosítójú értékekben bekövetkező egyidejű változásokra.

A billentyűkészlet lapozása olyan lapozási felületekhez megfelelő, ahol a felhasználó előre és hátra navigál, de nem támogatja a véletlenszerű hozzáférést, ahol a felhasználó bármely adott oldalra ugorhat. A véletlenszerű hozzáférési lapozáshoz eltolásos lapozás szükséges a fent leírtak szerint; az eltolásos lapozás hiányosságai miatt gondosan gondolja át, hogy valóban szükség van-e véletlenszerű hozzáférési lapozásra a használati esethez, vagy a következő/előző oldal navigációja elegendő-e. Ha véletlenszerű hozzáférési lapozásra van szükség, egy robusztus implementáció kulcskészlet-lapozást használhat a következő/előző lapra való navigáláskor, és eltolásos navigációt bármely más lapra ugráskor.

Több lapozási kulcs

Kulcskészlet-lapozás használatakor gyakran szükséges több tulajdonság szerinti sorrendbe rendezni. A következő lekérdezés például dátum és azonosító szerint lapoz:

var lastDate = new DateTime(2020, 1, 1);
var lastId = 55;
var nextPage = await context.Posts
    .OrderBy(b => b.Date)
    .ThenBy(b => b.PostId)
    .Where(b => b.Date > lastDate || (b.Date == lastDate && b.PostId > lastId))
    .Take(10)
    .ToListAsync();

Ez biztosítja, hogy a következő oldal pontosan ott folytatódjon, ahol az előző véget ért. További rendelési kulcsok hozzáadásakor további záradékok is hozzáadhatók.

Megjegyzés:

A legtöbb SQL-adatbázis támogatja a fentiek egyszerűbb és hatékonyabb verzióját a sorértékek használatával: WHERE (Date, Id) > (@lastDate, @lastId). Az EF Core jelenleg nem támogatja ezt a LINQ-lekérdezésekben, ezt a #26822 követi nyomon.

Indexes

Mint minden más lekérdezés esetében, a megfelelő indexelés elengedhetetlen a jó teljesítményhez: győződjön meg arról, hogy az indexek a lapszámozási sorrendnek megfelelőek. Ha egynél több oszlop szerint rendez, a több oszlopra vonatkozó index definiálható; ezt összetett indexnek nevezzük.

További információkért tekintse meg az indexek dokumentációs oldalát.

További erőforrások