Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
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:
- 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ő.
- 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
- Az eltolásalapú lapozás hiányosságairól és a billentyűkészlet-lapozásról ebben a bejegyzésben olvashat bővebben.
- .NET Data Community Standup session , ahol a lapozást és a fenti fogalmak bemutatóját tárgyaljuk.
- Az offset és a keyset lapszámozást összehasonlító részletes technikai bemutató. Bár a tartalom a PostgreSQL-adatbázissal foglalkozik, az általános információk más relációs adatbázisokra is érvényesek.
- A billentyűkészlet lapozását egyszerűsítő EF Core-bővítményekért lásd: MR. EntityFrameworkCore.KeysetPagination és MR. AspNetCore.Pagination.