Sayfalandırma
Sayfalandırma, sonuçların bir kerede değil, sayfalarda alınmasını ifade eder; bu genellikle, kullanıcının sonuçların sonraki veya önceki sayfasına gitmesine izin veren bir kullanıcı arabiriminin gösterildiği büyük sonuç kümeleri için yapılır.
Uyarı
Kullanılan sayfalandırma yönteminden bağımsız olarak, her zaman sıralamanızın tamamen benzersiz olduğundan emin olun. Örneğin, sonuçlar yalnızca tarihe göre sıralanıyorsa, ancak aynı tarihe sahip birden çok sonuç varsa, iki sayfalandırma sorgusunda farklı şekilde sıralandığından sonuçlar sayfalandırılırken atlanabilir. Hem tarihe hem de kimliğe göre (veya başka bir benzersiz özelliğe veya özellik birleşimine göre) sıralama tamamen benzersiz hale gelir ve bu sorundan kaçınır. İlişkisel veritabanlarının, birincil anahtara bile varsayılan olarak herhangi bir sıralama uygulamadığını unutmayın.
Not
Azure Cosmos DB'nin sayfalandırma için kendi mekanizması vardır. Ayrılmış belgeler sayfasına bakın.
Uzaklık sayfalaması
Veritabanlarıyla sayfalandırma uygulamanın yaygın yollarından biri ve Take
LINQ işleçlerini (OFFSET
ve LIMIT
SQL'de) kullanmaktırSkip
. 10 sonuç içeren bir sayfa boyutu verildiğinde, üçüncü sayfa EF Core ile aşağıdaki gibi getirilebilir:
var position = 20;
var nextPage = context.Posts
.OrderBy(b => b.PostId)
.Skip(position)
.Take(10)
.ToList();
Ne yazık ki, bu teknik çok sezgisel olsa da, bazı ciddi eksiklikleri de vardır:
- Uygulamaya döndürülmezse bile veritabanı ilk 20 girdiyi işlemeye devam etmelidir; bu, atlanan satır sayısıyla birlikte artan büyük olasılıkla önemli bir hesaplama yükü oluşturur.
- Herhangi bir güncelleştirme eşzamanlı olarak gerçekleşirse, sayfalandırmanız belirli girdileri atlayarak veya iki kez göstererek sonuçlanabilir. Örneğin, kullanıcı 2. sayfadan 3'e geçerken bir girdi kaldırılırsa, sonuç kümesinin tamamı "yukarı kaydırılır" ve bir giriş atlanır.
Anahtar kümesi sayfalaması
Bazen anahtar kümesi sayfalaması veya arama tabanlı sayfalandırma olarak da adlandırılan uzaklık tabanlı sayfalandırmaya önerilen alternatif, uzaklık yerine satırları atlamak için bir yan tümce kullanmaktırWHERE
. Bu, getirilen son girdiden (uzaklığı yerine) ilgili değerleri anımsamak ve bu satırdan sonraki satırları istemek anlamına gelir. Örneğin, son aldığımız sayfadaki son girdinin kimlik değeri 55 olduğunu varsayarsak, aşağıdakileri yapmamız yeterlidir:
var lastId = 55;
var nextPage = context.Posts
.OrderBy(b => b.PostId)
.Where(b => b.PostId > lastId)
.Take(10)
.ToList();
dizininde PostId
tanımlandığı varsayıldığında bu sorgu çok verimlidir ve aynı zamanda daha düşük kimlik değerlerinde gerçekleşen eş zamanlı değişikliklere duyarlı değildir.
Anahtar kümesi sayfalandırma, kullanıcının ileri ve geri gittiği ancak kullanıcının belirli bir sayfaya atlayabildiği rastgele erişimi desteklemediği sayfalandırma arabirimleri için uygundur. Rastgele erişim sayfalandırması, yukarıda açıklandığı gibi uzaklık sayfalandırması kullanılmasını gerektirir; uzaklık sayfalandırmasının eksiklikleri nedeniyle, kullanım örneğiniz için rastgele erişim sayfalandırmasının gerçekten gerekli olup olmadığını veya sonraki/önceki sayfa gezintisinin yeterli olup olmadığını dikkatlice göz önünde bulundurun. Rastgele erişim sayfalaması gerekiyorsa, sağlam bir uygulama sonraki/önceki sayfaya gezinti yaparken anahtar kümesi sayfalandırma ve başka bir sayfaya atlarken kaydırma gezintisi kullanabilir.
Birden çok sayfalandırma anahtarı
Anahtar kümesi sayfalandırma kullanılırken, birden fazla özelliğe göre sıralamak sık sık gereklidir. Örneğin, aşağıdaki sorgu tarihe ve kimliğe göre sayfalandırır:
var lastDate = new DateTime(2020, 1, 1);
var lastId = 55;
var nextPage = context.Posts
.OrderBy(b => b.Date)
.ThenBy(b => b.PostId)
.Where(b => b.Date > lastDate || (b.Date == lastDate && b.PostId > lastId))
.Take(10)
.ToList();
Bu, bir sonraki sayfanın tam olarak öncekinin sona erdiği yeri seçmesini sağlar. Daha fazla sıralama anahtarı eklendikçe ek yan tümceler eklenebilir.
Not
Çoğu SQL veritabanı, satır değerlerini kullanarak yukarıdakilerin daha basit ve daha verimli bir sürümünü destekler: WHERE (Date, Id) > (@lastDate, @lastId)
. EF Core şu anda LINQ sorgularında bu ifadeyi desteklememektedir, bu işlem #26822 tarafından izlenir.
Dizinler
Diğer sorgularda olduğu gibi, düzgün dizin oluşturma iyi performans için çok önemlidir: Dizinlerin sayfalandırma sıralamanıza karşılık gelen yerinde olduğundan emin olun. Birden fazla sütuna göre sıralama gerçekleştiriliyorsa, bu birden çok sütun üzerinde bir dizin tanımlanabilir; buna bileşik dizin adı verilir.
Daha fazla bilgi için dizinler hakkındaki belgeler sayfasına bakın.
Ek kaynaklar
- Uzaklık tabanlı sayfalandırmanın eksiklikleri ve anahtar kümesi sayfalaması hakkında daha fazla bilgi edinmek için bu gönderiye bakın.
- Sayfalandırmayı ele aldığımız ve yukarıdaki tüm kavramların tanıtımını yaptığımız .NET Veri Topluluğu Standup oturumu .
- Uzaklık ve anahtar kümesi sayfalandırmasını karşılaştıran teknik bir derinlemesine bakış sunusu . İçerik PostgreSQL veritabanıyla ilgilenirken, genel bilgiler diğer ilişkisel veritabanları için de geçerlidir.
- EF Core'un üzerinde bulunan ve anahtar kümesi sayfalandırmayı basitleştiren uzantılar için bkz . MR. EntityFrameworkCore.KeysetPagination ve MR. AspNetCore.Pagination.