Büyük Miktarlı Verileri Etkili Bir Şekilde Sayfalama (VB)
tarafından Scott Mitchell
Veri sunusu denetiminin varsayılan sayfalama seçeneği, temel alınan veri kaynağı denetimi yalnızca bir veri alt kümesi görüntülense bile tüm kayıtları aldığından, büyük miktarda veriyle çalışırken uygun değildir. Böyle durumlarda özel disk belleğine dönmemiz gerekir.
Giriş
Önceki öğreticide ele aldığımız gibi, disk belleği iki yoldan biriyle uygulanabilir:
- Varsayılan Sayfalama , veri Web denetiminin akıllı etiketindeki Disk Belleğini Etkinleştir seçeneği işaretlenerek uygulanabilir; Ancak, bir veri sayfası görüntülendiğinde ObjectDataSource, sayfada yalnızca bir alt kümesi görüntülense bile tüm kayıtları alır
- Özel Disk Belleği , veritabanından yalnızca kullanıcı tarafından istenen belirli bir veri sayfası için görüntülenmesi gereken kayıtları alarak varsayılan disk belleği performansını artırır; Ancak, özel disk belleği, varsayılan disk belleğinden biraz daha fazla çaba gerektirir
Uygulama kolaylığı nedeniyle bir onay kutusunu işaretleyin ve işiniz bitti! varsayılan sayfalama cazip bir seçenektir. Ancak tüm kayıtları almadaki saf yaklaşımı, yeterince büyük miktarda veri veya çok sayıda eşzamanlı kullanıcı içeren siteler için sayfalama yaparken bunu imkansız bir seçim haline getirir. Bu gibi durumlarda, duyarlı bir sistem sağlamak için özel disk belleğine dönmemiz gerekir.
Özel disk belleğinin zorluğu, belirli bir veri sayfası için gereken kesin kayıt kümesini döndüren bir sorgu yazabilmektir. Neyse ki, Microsoft SQL Server 2005 sıralama sonuçları için yeni bir anahtar sözcük sağlar ve bu anahtar sözcük kayıtların uygun alt kümesini verimli bir şekilde alabilen bir sorgu yazmamızı sağlar. Bu öğreticide, bir GridView denetiminde özel disk belleği uygulamak için bu yeni SQL Server 2005 anahtar sözcüğünü nasıl kullanacağınızı göreceğiz. Özel disk belleği için kullanıcı arabirimi, varsayılan sayfalama için aynı olsa da, özel disk belleği kullanarak bir sayfadan diğerine adımlama, varsayılan sayfalamadan daha hızlı birkaç büyüklüğe sahip olabilir.
Not
Özel disk belleği tarafından sergilenen tam performans artışı, sayfalandırılan toplam kayıt sayısına ve veritabanı sunucusuna yüklenen yüke bağlıdır. Bu öğreticinin sonunda, özel disk belleği aracılığıyla elde edilen performans avantajlarını gösteren bazı kaba ölçümlere göz atacağız.
1. Adım: Özel Disk Belleği İşlemini Anlama
Veriler arasında sayfalama yaparken, sayfada görüntülenen kesin kayıtlar istenen veri sayfasına ve sayfa başına görüntülenen kayıt sayısına bağlıdır. Örneğin, sayfa başına 10 ürün görüntüleyen 81 ürünü sayfalandırmak istediğimizi düşünün. İlk sayfayı görüntülerken 1 ile 10 arasında ürünler istiyoruz; ikinci sayfayı görüntülerken 11 ile 20 arasında vb. ürünlerle ilgilenirdik.
Hangi kayıtların alınması gerektiğini ve disk belleği arabiriminin nasıl işlendiğini belirleyen üç değişken vardır:
- Başlangıç Satırı Dizini görüntülenecek veri sayfasındaki ilk satırın dizini; Bu dizin, sayfa dizini, sayfa başına görüntülenecek kayıtlara çarpılarak ve bir tane eklenerek hesaplanabilir. Örneğin, ilk sayfa için (sayfa dizini 0 olan) bir kerede 10 kaydına sayfalama yaparken, Başlangıç Satırı Dizini 0 * 10 + 1 veya 1 olur; ikinci sayfa için (sayfa dizini 1 olan), Başlangıç Satırı Dizini 1 * 10 + 1 veya 11'dir.
- En Fazla Satır sayısı , sayfa başına görüntülenecek en fazla kayıt sayısıdır. Son sayfa için sayfa boyutundan daha az kayıt döndürülebileceği için bu değişkene en fazla satır sayısı denir. Örneğin, sayfa başına 10 kayıt içeren 81 üründe sayfalama yaparken, dokuzuncu ve son sayfada yalnızca bir kayıt olur. Ancak hiçbir sayfa En Fazla Satır değerinden daha fazla kayıt göstermez.
- Toplam Kayıt Sayısı , sayfalanan kayıtların toplam sayısını gösterir. Bu değişken belirli bir sayfa için hangi kayıtların alındığını belirlemek için gerekli olmasa da, disk belleği arabirimini dikte eder. Örneğin, sayfalandırma yapılan 81 ürün varsa, disk belleği arabirimi disk belleği kullanıcı arabiriminde dokuz sayfa numarası görüntülemeyi bilir.
Varsayılan sayfalama ile, Başlangıç Satırı Dizini sayfa dizininin ve sayfa boyutunun artı bir değeri olarak hesaplanırken, En Fazla Satır Sayısı yalnızca sayfa boyutudur. Varsayılan sayfalama, herhangi bir veri sayfası işlenirken veritabanındaki tüm kayıtları aldığından, her satırın dizini bilindiğinden, Başlangıç Satırı Dizini satırına geçme önemsiz bir görev haline gelir. Ayrıca, Yalnızca DataTable'daki kayıtların sayısı (veya veritabanı sonuçlarını tutmak için kullanılan nesne) olduğundan, Toplam Kayıt Sayısı kullanılabilir.
Başlangıç Satırı Dizini ve En Fazla Satır Sayısı değişkenleri göz önünde bulundurulduğunda, özel bir disk belleği uygulaması yalnızca Başlangıç Satırı Dizini'nde başlayan kayıtların kesin alt kümesini ve bundan sonra en fazla En Fazla Satır sayısı değerini döndürmelidir. Özel disk belleği iki zorluk sağlar:
- Belirtilen Başlangıç Satırı Dizininde kayıtları döndürmeye başlayabilmemiz için, bir satır dizinini sayfalanan verilerin tamamında yer alan her satırla verimli bir şekilde ilişkilendirebilmemiz gerekir
- Sayfalanan kayıtların toplam sayısını sağlamamız gerekiyor
Sonraki iki adımda bu iki sınamaya yanıt vermek için gereken SQL betiğini inceleyeceğiz. SQL betiğine ek olarak DAL ve BLL'de de yöntemler uygulamamız gerekir.
2. Adım: Sayfalanan Toplam Kayıt Sayısını Döndürme
Görüntülenen sayfa için kayıtların tam alt kümesinin nasıl alındığını incelemeden önce, sayfalandırılan kayıtların toplam sayısını nasıl döndürebileceğimize bakalım. Bu bilgiler, disk belleği kullanıcı arabirimini düzgün yapılandırmak için gereklidir. Belirli bir SQL sorgusu tarafından döndürülen toplam kayıt sayısı toplama işlevi kullanılarakCOUNT
elde edilebilir. Örneğin, tablodaki kayıtların toplam sayısını Products
belirlemek için aşağıdaki sorguyu kullanabiliriz:
SELECT COUNT(*)
FROM Products
DAL'ımıza bu bilgileri döndüren bir yöntem ekleyelim. Özellikle, yukarıda gösterilen deyimi yürüten SELECT
adlı TotalNumberOfProducts()
bir DAL yöntemi oluşturacağız.
İlk olarak Northwind.xsd
klasöründeki Yazılan Veri Kümesi dosyasını App_Code/DAL
açın. Ardından, Tasarım Aracı sağ tıklayın ProductsTableAdapter
ve Sorgu Ekle'yi seçin. Önceki öğreticilerde gördüğümüz gibi bu, DAL'ye çağrıldığında belirli bir SQL deyimini veya saklı yordamı yürütecek yeni bir yöntem eklememizi sağlayacaktır. Önceki öğreticilerdeki TableAdapter yöntemlerimizde olduğu gibi, bunun için geçici bir SQL deyimi kullanmayı tercih edin.
Şekil 1: Geçici SQL Deyimi Kullanma
Sonraki ekranda ne tür bir sorgu oluşturulacağını belirtebiliriz. Bu sorgu tek bir değer döndüreceğinden, skaler değer tablodaki Products
kayıtların toplam sayısını, bir tek değer seçeneği döndüren değeri seçin SELECT
.
Şekil 2: Sorguyu Tek Bir Değer Döndüren SELECT Deyimi Kullanacak Şekilde Yapılandırma
Kullanılacak sorgu türünü belirttikten sonra sorguyu belirtmemiz gerekir.
Şekil 3: SELECT COUNT(*) FROM Ürünler Sorgusunu Kullanma
Son olarak, yönteminin adını belirtin. Yukarıda belirtildiği gibi komutunu kullanalım TotalNumberOfProducts
.
Şekil 4: DAL Yöntemini TotalNumberOfProducts Olarak Adlandırın
Son'a tıkladıktan sonra sihirbaz, yöntemini DAL'ye ekler TotalNumberOfProducts
. SQL sorgusunun sonucu olması NULL
durumunda DAL'deki skaler dönüş yöntemleri null atanabilir türler döndürür. Ancak sorgumuz COUNT
her zaman değer olmayanNULL
bir değer döndürür; ne olursa olsun DAL yöntemi null atanabilir bir tamsayı döndürür.
DAL yöntemine ek olarak, BLL'de de bir yönteme ihtiyacımız vardır. ProductsBLL
Sınıf dosyasını açın ve DAL TotalNumberOfProducts
s yöntemine çağrıda bulunan bir TotalNumberOfProducts
yöntem ekleyin:
Public Function TotalNumberOfProducts() As Integer
Return Adapter.TotalNumberOfProducts().GetValueOrDefault()
End Function
DAL s TotalNumberOfProducts
yöntemi null atanabilir bir tamsayı döndürür; ancak standart bir tamsayı döndürmesi için s sınıfı TotalNumberOfProducts
yöntemini oluşturdukProductsBLL
. Bu nedenle, sınıf s TotalNumberOfProducts
yönteminin ProductsBLL
DAL TotalNumberOfProducts
s yöntemi tarafından döndürülen null atanabilir tamsayının değer bölümünü döndürmesini sağlamak zorundayız. çağrısı GetValueOrDefault()
, varsa, null atanabilir tamsayı değerini döndürür; ancak null atanabilir tamsayı ise null
, varsayılan tamsayı değerini döndürür( 0).
3. Adım: Kayıtların Kesin Alt Kümesini Döndürme
Sonraki görevimiz, DAL ve BLL'de daha önce açıklanan Başlangıç Satırı Dizini ve En Fazla Satır Sayısı değişkenlerini kabul eden yöntemler oluşturmak ve uygun kayıtları döndürmektir. Bunu yapmadan önce gerekli SQL betiğine göz atalım. Karşılaştığımız zorluk, yalnızca Başlangıç Satırı Dizini'nde (ve Kayıt Sayısı Üst Sınırı sayısı'na kadar) başlayarak yalnızca bu kayıtları döndürebilmemiz için, sayfalanan sonuçların tamamında her satıra verimli bir dizin atayabilmemiz gerektiğidir.
Veritabanı tablosunda satır dizini görevi görecek bir sütun varsa bu bir zorluk değildir. İlk bakışta, ilk ürün 1, ikinci bir ProductID
2 vb. olduğundan tablo ProductID
alanının yeterli olacağını düşünebilirizProducts
. Ancak, bir ürünün silinmesi dizide bir boşluk bırakarak bu yaklaşımı boş bırakır.
Satır dizinini sayfalanacak verilerle verimli bir şekilde ilişkilendirmek ve böylece kayıtların kesin alt kümesinin alınmasına olanak sağlamak için kullanılan iki genel teknik vardır:
SQL Server 2005 s
ROW_NUMBER()
anahtar sözcüğü SQL Server 2005'e yeni kullanıldığında,ROW_NUMBER()
anahtar sözcük bir sıralamaya göre döndürülen her kayıtla bir derecelendirmeyi ilişkilendirir. Bu derecelendirme her satır için satır dizini olarak kullanılabilir.Tablo Değişkeni kullanma ve
SET ROWCOUNT
SQL Server deyimiSET ROWCOUNT
, bir sorguyu sonlandırmadan önce kaç tane toplam kaydın işlenmesi gerektiğini belirtmek için kullanılabilir; tablo değişkenleri, geçici tablolara benzer şekilde tablo verilerini tutabilen yerel T-SQL değişkenleridir. Bu yaklaşım hem Microsoft SQL Server 2005 hem de SQL Server 2000 ile aynı derecede iyi çalışır (ancakROW_NUMBER()
yaklaşım yalnızca SQL Server 2005 ile çalışır).Buradaki fikir, verileri sayfalanan tablonun birincil anahtarları için bir sütun ve sütunlar içeren bir
IDENTITY
tablo değişkeni oluşturmaktır. Ardından, verileri sayfalanan tablonun içeriği tablo değişkenine atılır ve böylece tablodaki her kayıt için sıralı satır dizini (sütun aracılığıylaIDENTITY
) ilişkilendirilir. Tablo değişkeni doldurulduktan sonra, tablo değişkeninde temel tabloyla birleştirilen birSELECT
deyim yürütülerek belirli kayıtların çekilmesi gerçekleştirilebilir.SET ROWCOUNT
deyimi, tablo değişkenine atılması gereken kayıt sayısını akıllı bir şekilde sınırlamak için kullanılır.Bu yaklaşımın verimliliği, istenen sayfa numarasını temel alır, değere
SET ROWCOUNT
Başlangıç Satırı Dizini artı En Fazla Satır değeri atanır. Verilerin ilk birkaç sayfası gibi düşük numaralı sayfalarda sayfalama yaparken bu yaklaşım çok verimlidir. Ancak, sonuna yakın bir sayfayı alırken varsayılan sayfalama benzeri performans sergiler.
Bu öğretici, anahtar sözcüğünü ROW_NUMBER()
kullanarak özel disk belleği uygular. Tablo değişkenini ve SET ROWCOUNT
tekniğini kullanma hakkında daha fazla bilgi için bkz. Büyük Sonuç Kümeleri Aracılığıyla Sayfalama için Daha Verimli Bir Yöntem.
Anahtar sözcüğü, ROW_NUMBER()
aşağıdaki söz dizimini kullanarak belirli bir sıralama üzerinden döndürülen her kayıtla bir derecelendirme ilişkilendirdi:
SELECT columnList,
ROW_NUMBER() OVER(orderByClause)
FROM TableName
ROW_NUMBER()
, belirtilen sıralamayla ilgili olarak her kaydın derecesini belirten sayısal bir değer döndürür. Örneğin, her ürünün en pahalıdan en ucuza sıralanmış sıralamasını görmek için aşağıdaki sorguyu kullanabiliriz:
SELECT ProductName, UnitPrice,
ROW_NUMBER() OVER(ORDER BY UnitPrice DESC) AS PriceRank
FROM Products
Şekil 5'te, Visual Studio'da sorgu penceresinde çalıştırıldığında bu sorgunun sonuçları gösterilir. Ürünlerin her satır için bir fiyat sıralamasıyla birlikte fiyata göre sıralandığını unutmayın.
Şekil 5: Döndürülen Her Kayıt için Fiyat Derecelendirmesi Dahil Edildi
Not
ROW_NUMBER()
SQL Server 2005'te sunulan birçok yeni derecelendirme işlevinden yalnızca biridir. diğer derecelendirme işlevleriyle birlikte daha kapsamlı bir tartışma ROW_NUMBER()
için ROW_NUMBER belgeleri okuyun.
Sonuçları yan tümcesinde OVER
belirtilen ORDER BY
sütuna göre sıralarken (UnitPrice
yukarıdaki örnekte) SQL Server sonuçları sıralamanız gerekir. Sonuçların sıralandığı sütunlar üzerinde kümelenmiş bir dizin varsa veya kapsayan bir dizin varsa, ancak aksi takdirde daha maliyetli olabilirse bu hızlı bir işlemdir. Yeterince büyük sorgularda performansı artırmaya yardımcı olmak için, sonuçların sıralandığı sütun için kümelenmemiş bir dizin eklemeyi göz önünde bulundurun. Performansla ilgili önemli noktalara daha ayrıntılı bir bakış için bkz. SQL Server 2005'te Derecelendirme İşlevleri ve Performans.
tarafından ROW_NUMBER()
döndürülen derecelendirme bilgileri yan tümcesinde WHERE
doğrudan kullanılamaz. Ancak, sonucu döndürmek ROW_NUMBER()
için türetilmiş bir tablo kullanılabilir ve bu tablo yan tümcesinde WHERE
görüntülenebilir. Örneğin, aşağıdaki sorgu sonucun yanı sıra ROW_NUMBER()
ProductName ve UnitPrice sütunlarını döndürmek için türetilmiş bir tablo kullanır ve ardından yalnızca fiyat derecesi 11 ile 20 arasında olan ürünleri döndürmek için bir WHERE
yan tümce kullanır:
SELECT PriceRank, ProductName, UnitPrice
FROM
(SELECT ProductName, UnitPrice,
ROW_NUMBER() OVER(ORDER BY UnitPrice DESC) AS PriceRank
FROM Products
) AS ProductsWithRowNumber
WHERE PriceRank BETWEEN 11 AND 20
Bu kavramı biraz daha genişleterek, istenen Başlangıç Satırı Dizini ve En Fazla Satır Sayısı değerlerine göre belirli bir veri sayfasını almak için bu yaklaşımı kullanabiliriz:
SELECT PriceRank, ProductName, UnitPrice
FROM
(SELECT ProductName, UnitPrice,
ROW_NUMBER() OVER(ORDER BY UnitPrice DESC) AS PriceRank
FROM Products
) AS ProductsWithRowNumber
WHERE PriceRank > <i>StartRowIndex</i> AND
PriceRank <= (<i>StartRowIndex</i> + <i>MaximumRows</i>)
Not
Bu öğreticinin ilerleyen bölümlerinde göreceğimiz gibi, StartRowIndex
ObjectDataSource tarafından sağlanan sıfırdan başlayarak dizinlenirkenROW_NUMBER()
, SQL Server 2005 tarafından döndürülen değer 1'den başlayarak dizinlenir. Bu nedenle yan tümcesi, WHERE
kesinlikle değerinden büyük ve değerinden StartRowIndex
küçük veya eşit StartRowIndex
+ MaximumRows
olan PriceRank
kayıtları döndürür.
Başlangıç Satırı Dizini ve En Fazla Satır değerleri göz önüne alındığında belirli bir veri sayfasını almak için nasıl ROW_NUMBER()
kullanılabileceğini ele aldığımıza göre, şimdi bu mantığı DAL ve BLL'de yöntemler olarak uygulamamız gerekiyor.
Bu sorguyu oluştururken sonuçların derecelendirileceği sıralamaya karar vermemiz gerekir; şimdi ürünleri adlarına göre alfabetik düzende sıralayalım. Başka bir deyişle, bu öğreticideki özel disk belleği uygulamasıyla, sıralanabilir durumdan daha özel bir disk belleği raporu oluşturamayacağız. Ancak sonraki öğreticide bu tür işlevlerin nasıl sağlandığını göreceğiz.
Önceki bölümde DAL yöntemini geçici bir SQL deyimi olarak oluşturduk. Ne yazık ki, TableAdapter sihirbazı tarafından kullanılan Visual Studio'daki T-SQL ayrıştırıcısı, işlev tarafından kullanılan söz dizimini ROW_NUMBER()
beğenmiyorOVER
. Bu nedenle, bu DAL yöntemini saklı yordam olarak oluşturmamız gerekir. Görünüm menüsünden Sunucu Gezgini'ni seçin (veya Ctrl+Alt+S tuşlarına basın) ve düğümü genişletin NORTHWND.MDF
. Yeni saklı yordam eklemek için Saklı Yordamlar düğümüne sağ tıklayın ve Yeni Saklı Yordam Ekle'yi seçin (bkz. Şekil 6).
Şekil 6: Ürünler Aracılığıyla Disk Belleği için Yeni Bir Saklı Yordam Ekleme
Bu saklı yordam iki tamsayı giriş parametresi @startRowIndex
kabul etmeli ve yalnızca belirtilenden @startRowIndex
büyük ve @maximumRows
s değerinden ROW_NUMBER()
ProductName
küçük veya buna eşit @startRowIndex
+ @maximumRow
satırları döndürerek alan tarafından sıralanmış işlevini kullanmalıdır. Yeni saklı yordama aşağıdaki betiği girin ve kaydet simgesine tıklayarak saklı yordamı veritabanına ekleyin.
CREATE PROCEDURE dbo.GetProductsPaged
(
@startRowIndex int,
@maximumRows int
)
AS
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit,
UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued,
CategoryName, SupplierName
FROM
(
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit,
UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued,
(SELECT CategoryName
FROM Categories
WHERE Categories.CategoryID = Products.CategoryID) AS CategoryName,
(SELECT CompanyName
FROM Suppliers
WHERE Suppliers.SupplierID = Products.SupplierID) AS SupplierName,
ROW_NUMBER() OVER (ORDER BY ProductName) AS RowRank
FROM Products
) AS ProductsWithRowNumbers
WHERE RowRank > @startRowIndex AND RowRank <= (@startRowIndex + @maximumRows)
Saklı yordamı oluşturduktan sonra test etmek için biraz zaman ayırın. Sunucu Gezgini'nde GetProductsPaged
saklı yordam adına sağ tıklayın ve Yürüt seçeneğini belirleyin. Ardından Visual Studio sizden giriş parametrelerini ve @maximumRow
s değerlerini @startRowIndex
ister (bkz. Şekil 7). Farklı değerleri deneyin ve sonuçları inceleyin.
ve @maximumRows Parameters" /> için bir Değer girin
Şekil 7: ve @maximumRows Parametreleri için @startRowIndex Bir Değer Girme
Bu giriş parametreleri değerlerini seçtikten sonra Çıkış penceresi sonuçları gösterir. Şekil 8'de hem hem de parametreleri için 10 geçirildiğinde eldeki @startRowIndex
@maximumRows
sonuçlar gösterilmektedir.
Şekil 8: İkinci Veri Sayfasında Görüntülenecek Kayıtlar Döndürülür (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Bu saklı yordam oluşturulduktan sonra yöntemini oluşturmaya ProductsTableAdapter
hazırız. Yazılan Veri Kümesi'ni Northwind.xsd
ProductsTableAdapter
açın, öğesine sağ tıklayın ve Sorgu Ekle seçeneğini belirleyin. Geçici bir SQL deyimi kullanarak sorgu oluşturmak yerine mevcut saklı yordamı kullanarak oluşturun.
Şekil 9: Mevcut Saklı Yordamı Kullanarak DAL Yöntemi Oluşturma
Ardından çağrılacak saklı yordamı seçmeniz istenir. Açılan listeden GetProductsPaged
saklı yordamı seçin.
Şekil 10: Drop-Down Listesinden GetProductsPaged Saklı Yordamını Seçin
Sonraki ekranda saklı yordam tarafından döndürülen veri türü sorılır: tablosal veriler, tek bir değer veya değer yok. GetProductsPaged
Saklı yordam birden çok kayıt döndürebileceğinden tablo verileri döndürdüğünü belirtin.
Şekil 11: Saklı Yordamın Tablo verileri döndürdüğünü belirtme
Son olarak, oluşturmak istediğiniz yöntemlerin adlarını belirtin. Önceki öğreticilerimizde olduğu gibi devam edin ve hem DataTable'ı Doldur hem de DataTable Döndür'ünü kullanarak yöntemler oluşturun. İlk yöntemi ve ikincisini FillPaged
GetProductsPaged
olarak adlandırın.
Şekil 12: Yöntemleri FillPaged ve GetProductsPaged Olarak Adlandırın
Belirli bir ürün sayfasını döndürmek için bir DAL yöntemi oluşturmanın yanı sıra, BLL'de de bu işlevleri sağlamamız gerekir. DAL yönteminde olduğu gibi, BLL'nin GetProductsPaged yöntemi de Başlangıç Satırı Dizini ve Maksimum Satırlar'ı belirtmek için iki tamsayı girişi kabul etmeli ve yalnızca belirtilen aralıkta yer alan kayıtları döndürmelidir. ProductsBLL sınıfında yalnızca DAL'nin GetProductsPaged yöntemine çağrıda bulunan böyle bir BLL yöntemi oluşturun, örneğin:
<System.ComponentModel.DataObjectMethodAttribute( _
System.ComponentModel.DataObjectMethodType.Select, False)> _
Public Function GetProductsPaged(startRowIndex As Integer, maximumRows As Integer) _
As Northwind.ProductsDataTable
Return Adapter.GetProductsPaged(startRowIndex, maximumRows)
End Function
BLL yönteminin giriş parametreleri için herhangi bir ad kullanabilirsiniz, ancak kısa bir süre sonra göreceğimiz gibi, kullanmayı startRowIndex
maximumRows
seçip bir ObjectDataSource'u bu yöntemi kullanacak şekilde yapılandırırken bizi fazladan bir çalışmadan kurtarır.
4. Adım: ObjectDataSource'un Özel Disk Belleği Kullanacak Şekilde Yapılandırılması
Kayıtların belirli bir alt kümesine erişmeye yönelik BLL ve DAL yöntemleri tamamlandığında, özel disk belleği kullanarak temel alınan kayıtlarda sayfalanan bir GridView denetimi oluşturmaya hazırız. Başlangıç olarak klasördeki PagingAndSorting
sayfayı EfficientPaging.aspx
açın, sayfaya bir GridView ekleyin ve bunu yeni bir ObjectDataSource denetimi kullanacak şekilde yapılandırın. Geçmiş öğreticilerimizde genellikle ObjectDataSource sınıfın ProductsBLL
GetProducts
yöntemini kullanacak şekilde yapılandırılırdı. Ancak bu kez yöntemini kullanmak GetProductsPaged
istiyoruz çünkü GetProducts
yöntem veritabanındaki tüm ürünleri döndürürken GetProductsPaged
kayıtların yalnızca belirli bir alt kümesini döndürür.
Şekil 13: ObjectDataSource'ı ProductsBLL Sınıfının GetProductsPaged Yöntemini Kullanacak Şekilde Yapılandırma
Salt okunur bir GridView oluşturduğumuz için INSERT, UPDATE ve DELETE sekmelerindeki yöntem açılan listesini (Yok) olarak ayarlamak için biraz zaman ayırın.
Ardından, ObjectDataSource sihirbazı yöntem s startRowIndex
ve maximumRows
giriş parametreleri değerlerinin GetProductsPaged
kaynaklarını sorar. Bu giriş parametreleri aslında GridView tarafından otomatik olarak ayarlanır, bu nedenle kaynağı Yok olarak bırakıp Son'a tıklamanız yeterlidir.
Şekil 14: Giriş Parametresi Kaynaklarını Yok olarak bırakın
ObjectDataSource sihirbazını tamamladıktan sonra GridView, ürün veri alanlarının her biri için bir BoundField veya CheckBoxField içerir. GridView görünümünü uygun gördüğünüz şekilde özelleştirebilirsiniz. Yalnızca , , CategoryName
SupplierName
, QuantityPerUnit
ve UnitPrice
BoundField değerlerini görüntülemeyi ProductName
tercih ettim. Ayrıca, akıllı etiketinde Disk Belleğini Etkinleştir onay kutusunu işaretleyerek GridView'u disk belleğini destekleyecek şekilde yapılandırın. Bu değişikliklerden sonra GridView ve ObjectDataSource bildirim temelli işaretlemesi aşağıdakine benzer olmalıdır:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="SupplierName" HeaderText="Supplier"
SortExpression="SupplierName" />
<asp:BoundField DataField="QuantityPerUnit" HeaderText="Qty/Unit"
SortExpression="QuantityPerUnit" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False" SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetProductsPaged"
TypeName="ProductsBLL">
<SelectParameters>
<asp:Parameter Name="startRowIndex" Type="Int32" />
<asp:Parameter Name="maximumRows" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
Ancak sayfayı bir tarayıcı üzerinden ziyaret ederseniz GridView bulunabilecek bir yer değildir.
Şekil 15: GridView Görüntülenmiyor
ObjectDataSource şu anda hem maximumRows
hem de giriş parametrelerinin değerleri olarak 0 kullandığından GetProductsPaged
startRowIndex
GridView eksik. Bu nedenle, sonuçta elde edilen SQL sorgusu hiçbir kayıt döndürmez ve bu nedenle GridView görüntülenmez.
Bunu düzeltmek için ObjectDataSource'u özel disk belleği kullanacak şekilde yapılandırmamız gerekir. Bu, aşağıdaki adımlarda gerçekleştirilebilir:
- ObjectDataSource s
EnablePaging
özelliğinitrue
, ObjectDataSource'a iki ek parametreyeSelectMethod
geçirmesi gerektiğini gösterecek şekilde ayarlayın: biri Başlangıç Satırı Dizinini ()StartRowIndexParameterName
belirtmek için, biri de En Fazla Satır Sayısını (MaximumRowsParameterName
) belirtmek için. - ObjectDataSource s
StartRowIndexParameterName
veMaximumRowsParameterName
Özelliklerini Ayarlayın BunaStartRowIndexParameterName
göre veMaximumRowsParameterName
özellikleri, özel disk belleği amacıyla içine geçirilen giriş parametrelerininSelectMethod
adlarını gösterir. Varsayılan olarak, bu parametre adları vemaximumRows
şeklindedirstartIndexRow
. Bu nedenle, BLL'de yöntemi oluştururkenGetProductsPaged
giriş parametreleri için bu değerleri kullandım. BLLGetProductsPaged
yöntemi için vemaxRows
gibistartIndex
farklı parametre adları kullanmayı seçtiyseniz, örneğin ObjectDataSource sStartRowIndexParameterName
veMaximumRowsParameterName
özelliklerini buna göre ayarlamanız gerekir (örneğin, içinStartRowIndexParameterName
startIndex ve maxRowsMaximumRowsParameterName
). - ObjectDataSource s
SelectCountMethod
Özelliğini, Sayfalanan Kayıtların Toplam Sayısını Döndüren Yöntemin Adı olarak ayarlayın (TotalNumberOfProducts
), sınıfınTotalNumberOfProducts
yöntemininProductsBLL
sorguyu yürütenSELECT COUNT(*) FROM Products
bir DAL yöntemi kullanılarak sayfalanan kayıtların toplam sayısını döndürdüğünü hatırlayın. Bu bilgiler, disk belleği arabirimini doğru bir şekilde işlemek için ObjectDataSource tarafından gereklidir. - Sihirbaz aracılığıyla ObjectDataSource'u yapılandırırken ObjectDataSource bildirim temelli işaretlemesinden ve
maximumRows
<asp:Parameter>
öğelerini kaldırın. Visual Studio, yöntemin giriş parametreleri için otomatik olarak iki öğe ekler.startRowIndex
<asp:Parameter>
GetProductsPaged
olarak ayarlanarakEnablePaging
true
, bu parametreler otomatik olarak geçirilir; bildirim temelli söz diziminde de görünürlerse, ObjectDataSource yönteme dört parametre ve yöntemeGetProductsPaged
iki parametre geçirmeyiTotalNumberOfProducts
dener. Bu<asp:Parameter>
öğeleri kaldırmayı unutursanız, sayfayı bir tarayıcı üzerinden ziyaret ettiğinizde şöyle bir hata iletisi alırsınız: ObjectDataSource 'ObjectDataSource1', parametreleri olan genel olmayan bir 'TotalNumberOfProducts' yöntemini bulamadı: startRowIndex, maximumRows.
Bu değişiklikleri yaptıktan sonra ObjectDataSource'un bildirim temelli söz dizimi aşağıdaki gibi görünmelidir:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetProductsPaged"
TypeName="ProductsBLL" EnablePaging="True" SelectCountMethod="
TotalNumberOfProducts">
</asp:ObjectDataSource>
EnablePaging
ve SelectCountMethod
özelliklerinin ayarlandığını ve <asp:Parameter>
öğelerin kaldırıldığını unutmayın. Şekil 16'da, bu değişiklikler yapıldıktan sonra Özellikler penceresi ekran görüntüsü gösterilmektedir.
Şekil 16: Özel Disk Belleği kullanmak için ObjectDataSource Denetimini Yapılandırma
Bu değişiklikleri yaptıktan sonra bu sayfayı bir tarayıcı üzerinden ziyaret edin. Alfabetik olarak sıralanmış 10 ürünün listelendiğini görmeniz gerekir. Verileri tek gözden geçirerek adım adım ilerleyin. Varsayılan sayfalama ile özel sayfalama arasındaki son kullanıcı perspektifinden görsel bir fark olmasa da, yalnızca belirli bir sayfa için görüntülenmesi gereken kayıtları aldığından, özel sayfalama büyük miktarda veri üzerinden daha verimli sayfalar oluşturur.
Şekil 17: Ürün Adına Göre Sıralanmış Veriler, Özel Sayfalama Kullanılarak Sayfalanmıştır (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Not
Özel disk belleğiyle, ObjectDataSource'lar SelectCountMethod
tarafından döndürülen sayfa sayısı değeri GridView'un görünüm durumunda depolanır. , EditIndex
, , SelectedIndex
DataKeys
koleksiyonu vb. diğer GridView değişkenleriPageIndex
, GridView EnableViewState
özelliğinin değerinden bağımsız olarak kalıcı olan denetim durumunda depolanır. PageCount
Değer, görünüm durumu kullanılarak geri göndermeler arasında kalıcı hale geldiğinden, sizi son sayfaya götürecek bir bağlantı içeren bir disk belleği arabirimi kullanılırken GridView'un görünüm durumunun etkinleştirilmesi zorunludur. (Disk belleği arabiriminiz son sayfaya doğrudan bağlantı içermiyorsa, görünüm durumunu devre dışı bırakabilirsiniz.)
Son sayfa bağlantısına tıklanması geri göndermeye neden olur ve GridView'a özelliğini güncelleştirmesini emreder PageIndex
. Son sayfa bağlantısına tıklanırsa, GridView özelliğini özelliğinden PageCount
bir daha küçük bir değere atarPageIndex
. Görünüm durumu devre dışı olduğunda, PageCount
değer geri göndermeler arasında kaybolur ve PageIndex
yerine en büyük tamsayı değeri atanır. Ardından GridView, ve PageCount
özelliklerini çarparak başlangıç satırı dizinini belirlemeye PageSize
çalışır. Bu, ürünün izin verilen en büyük tamsayı boyutunu aşması sonucu verir OverflowException
.
Özel Sayfalama ve Sıralama Uygulama
Geçerli özel disk belleği uygulamamız, saklı yordam oluşturulurken verilerin sayfalandırma sırasının GetProductsPaged
statik olarak belirtilmesi gerekir. Ancak, GridView akıllı etiketinin, Sayfalandırmayı Etkinleştir seçeneğine ek olarak Sıralamayı Etkinleştir onay kutusu içerdiğini de belirtmiş olabilirsiniz. Ne yazık ki, geçerli özel disk belleği uygulamamızla GridView'a sıralama desteği eklemek yalnızca o anda görüntülenen veri sayfasındaki kayıtları sıralar. Örneğin, GridView'u sayfalandırmayı da destekleyecek şekilde yapılandırdığınızda, ilk veri sayfasını görüntülerken ürün adına göre azalan düzende sıralarsanız, 1. sayfadaki ürünlerin sırasını tersine çevirir. Şekil 18'de gösterildiği gibi, ters alfabetik sırada sıralanırken ilk ürün olarak Carnarvon Kaplanları gösterilir ve bu da Alfabetik olarak Carnarvon Kaplanları'nın ardından gelen diğer 71 ürünü yoksayar; sıralamada yalnızca ilk sayfadaki kayıtlar dikkate alınır.
Şekil 18: Yalnızca Geçerli Sayfada Gösterilen Veriler Sıralanır (Tam boyutlu resmi görüntülemek için tıklayın)
Sıralama yalnızca geçerli veri sayfası için geçerlidir çünkü sıralama BLL'nin GetProductsPaged
yönteminden veriler alındıktan sonra gerçekleşir ve bu yöntem yalnızca belirli bir sayfa için bu kayıtları döndürür. Sıralamayı doğru uygulamak için, verilerin belirli bir veri sayfasını döndürmeden önce uygun şekilde derecelenebilmesi için GetProductsPaged
sıralama ifadesini yöntemine geçirmemiz gerekir. Sonraki öğreticimizde bunu nasıl gerçekleştirebileceğimizi göreceğiz.
Özel Sayfalama ve Silme Uygulama
Verileri özel sayfalama teknikleri kullanılarak disk belleğine alınan bir GridView'da işlevselliği silmeyi etkinleştirirseniz, son kaydı son sayfadan silerken GridView'un GridView'larını PageIndex
uygun şekilde azaltmaktansa kaybolduğunu görürsünüz. Bu hatayı yeniden oluşturmak için az önce oluşturduğumuz öğreticide silmeyi etkinleştirin. Bir kerede 81 ürün, 10 ürün arasından sayfalama yaptığımız için tek bir ürün görmeniz gereken son sayfaya (sayfa 9) gidin. Bu ürünü silin.
Son ürünü sildikten sonra GridView otomatik olarak sekizinci sayfaya gitmelidir ve bu tür işlevler varsayılan sayfalama ile gösterilir. Ancak özel sayfalama ile, son sayfadaki son ürünü sildikten sonra GridView ekrandan tamamen kaybolur. Bunun kesin nedeni , bu öğreticinin kapsamının biraz dışındadır; Bu sorunun kaynağıyla ilgili alt düzey ayrıntılar için bkz. Custom Paging ile GridView'dan Son Sayfadaki Son Kaydı Silme . Özet olarak, Sil düğmesine tıklandığında GridView tarafından gerçekleştirilen aşağıdaki adım dizilerinden kaynaklanır:
- Kaydı silme
- Belirtilen
PageIndex
ve için görüntülenecek uygun kayıtları alınPageSize
- veri kaynağındaki veri sayfalarının sayısını aşmadığından emin olun
PageIndex
; aşıyorsa GridView sPageIndex
özelliğini otomatik olarak azaltma - 2. Adımda elde edilen kayıtları kullanarak uygun veri sayfasını GridView'a bağlama
Sorun, 2 PageIndex
. Adım'da görüntülenecek kayıtları yakalarken kullanılanın, tek kaydı yeni silinmiş olan son sayfanın yine PageIndex
de olması gerçeğinden kaynaklanır. Bu nedenle, 2. Adımda, bu son veri sayfasında artık kayıt bulunmadığından hiçbir kayıt döndürülmüyor. Ardından, 3. Adımda GridView, özelliğinin PageIndex
veri kaynağındaki toplam sayfa sayısından (son sayfadaki son kaydı sildiğimizden) büyük olduğunu fark eder ve bu nedenle özelliğini geri PageIndex
alır. 4. Adımda GridView kendisini 2. Adımda alınan verilere bağlamaya çalışır; ancak, 2. Adımda hiçbir kayıt döndürülmedi, bu nedenle boş bir GridView ile sonuçlandı. Varsayılan disk belleğinde, 2. Adımda tüm kayıtlar veri kaynağından alındığından bu sorun ortaya çıkmaz.
Bunu düzeltmek için iki seçeneğimiz vardır. İlki, GridView'un RowDeleted
olay işleyicisi için, yeni silinen sayfada kaç kaydın görüntülendiğini belirleyen bir olay işleyicisi oluşturmaktır. Yalnızca bir kayıt varsa, yeni silinen kaydın son kayıt olması gerekir ve GridView'ın PageIndex
öğesini azaltmamız gerekir. Elbette, yalnızca silme işleminin başarılı olması durumunda değerini güncelleştirmek PageIndex
istiyoruz. Bu işlem, özelliğinin e.Exception
olduğundan null
emin olarak belirlenebilir.
Bu yaklaşım işe yarar çünkü 1. adımdan PageIndex
sonraki ama 2. Adımdan öncekileri güncelleştirir. Bu nedenle, 2. Adımda uygun kayıt kümesi döndürülür. Bunu gerçekleştirmek için aşağıdaki gibi bir kod kullanın:
Protected Sub GridView1_RowDeleted(sender As Object, e As GridViewDeletedEventArgs) _
Handles GridView1.RowDeleted
' If we just deleted the last row in the GridView, decrement the PageIndex
If e.Exception Is Nothing AndAlso GridView1.Rows.Count = 1 Then
' we just deleted the last row
GridView1.PageIndex = Math.Max(0, GridView1.PageIndex - 1)
End If
End Sub
Alternatif bir geçici çözüm, ObjectDataSource RowDeleted
olayı için bir olay işleyicisi oluşturmak ve özelliğini 1 değerine ayarlamaktır AffectedRows
. 1. Adımda kaydı sildikten sonra (ancak 2. Adımda verileri yeniden almadan önce), gridview işlemden bir veya daha fazla satır etkilendiyse özelliğini güncelleştirir PageIndex
. Ancak, AffectedRows
özelliği ObjectDataSource tarafından ayarlanmaz ve bu nedenle bu adım atlanır. Bu adımı yürütmenin bir yolu, silme işlemi başarıyla tamamlanırsa özelliği el ile ayarlamaktır AffectedRows
. Bu, aşağıdaki gibi bir kod kullanılarak gerçekleştirilebilir:
Protected Sub ObjectDataSource1_Deleted( _
sender As Object, e As ObjectDataSourceStatusEventArgs) _
Handles ObjectDataSource1.Deleted
' If we get back a Boolean value from the DeleteProduct method and it's true, then
' we successfully deleted the product. Set AffectedRows to 1
If TypeOf e.ReturnValue Is Boolean AndAlso CType(e.ReturnValue, Boolean) = True Then
e.AffectedRows = 1
End If
End Sub
Bu olay işleyicilerinin her ikisinin de kodu, örneğin arka planda kod sınıfında EfficientPaging.aspx
bulunabilir.
Varsayılan ve Özel Disk BelleğiNin Performansını Karşılaştırma
Özel disk belleği yalnızca gerekli kayıtları aldığından, varsayılan disk belleği görüntülenen her sayfanın tüm kayıtlarını döndürürken, özel disk belleğinin varsayılan disk belleğinden daha verimli olduğu açıktır. Ama özel disk belleği ne kadar daha verimlidir? Varsayılan disk belleğinden özel disk belleğine geçerek ne tür performans kazançları görülebilir?
Ne yazık ki buradaki tüm yanıtlara uyan bir boyut yoktur. Performans artışı bir dizi faktöre bağlıdır; en belirgin ikisi, sayfalanan kayıtların sayısı ve veritabanı sunucusuna yerleştirilen yük ve web sunucusu ile veritabanı sunucusu arasındaki iletişim kanallarıdır. Yalnızca birkaç düzine kaydı olan küçük tablolar için performans farkı göz ardı edilebilir. Ancak binlerce ile yüz binlerce satırı olan büyük tablolarda performans farkı oldukça yüksektir.
"SQL Server 2005 ile ASP.NET 2.0'da Özel Disk Belleği" makalem, 50.000 kayıt içeren bir veritabanı tablosunda disk belleği yaparken bu iki disk belleği tekniği arasındaki performans farklarını görüntülemek için çalıştırdığım bazı performans testlerini içeriyor. Bu testlerde hem SQL Server düzeyinde (SQL Profiler kullanarak) hem de ASP.NET izleme özelliklerini kullanarak ASP.NET sayfasında sorguyu yürütme süresini inceledim. Bu testlerin geliştirme kutumda tek bir etkin kullanıcıyla çalıştırıldığını ve bu nedenle bilimsel olmadığını ve tipik web sitesi yük desenlerini taklit etmediğini unutmayın. Ne olursa olsun, sonuçlar yeterince büyük miktarda veriyle çalışırken varsayılan ve özel disk belleği için yürütme süresindeki göreli farkları gösterir.
Ort. Süre (sn) | Okur | |
---|---|---|
Varsayılan Disk Belleği SQL Profil Oluşturucu | 1.411 | 383 |
Özel Disk Belleği SQL Profil Oluşturucu | 0.002 | 29 |
Varsayılan Disk Belleği ASP.NET İzleme | 2.379 | Yok |
Özel Disk Belleği ASP.NET İzleme | 0.029 | Yok |
Gördüğünüz gibi, belirli bir veri sayfası alınırken ortalama olarak 354 daha az okuma gerekir ve bu sürenin bir bölümünde tamamlanır. ASP.NET sayfasında, özel olarak sayfa varsayılan disk belleği kullanılırken geçen sürenin 1/100'ünde işlenebiliyordu.
Özet
Varsayılan sayfalama, veri Web denetiminin akıllı etiketinde Disk Belleğini Etkinleştir onay kutusunu işaretlemek için bir özelliktir, ancak bu basitlik performans maliyetine neden olur. Varsayılan sayfalama ile, kullanıcı herhangi bir veri sayfası istediğinde, yalnızca küçük bir bölümü gösterilse bile tüm kayıtlar döndürülür. ObjectDataSource, bu performans yüküyle mücadele etmek için alternatif bir disk belleği seçeneği özel disk belleği sunar.
Özel disk belleği, yalnızca görüntülenmesi gereken kayıtları alarak varsayılan disk belleği performans sorunlarına göre geliştirilse de, özel disk belleği uygulamak daha önemlidir. İlk olarak, istenen kayıtların belirli bir alt kümesine doğru (ve verimli bir şekilde) erişen bir sorgu yazılmalıdır. Bu, çeşitli yollarla gerçekleştirilebilir; bu öğreticide incelediğimiz, sonuçları sıralamak için SQL Server 2005'in yeni ROW_NUMBER()
işlevini kullanmak ve ardından yalnızca derecelendirmesi belirtilen aralık içinde olan sonuçları döndürmektir. Ayrıca, sayfalanan kayıtların toplam sayısını belirlemek için bir araç eklememiz gerekir. Bu DAL ve BLL yöntemlerini oluşturduktan sonra, toplam kaç kaydın sayfalandığını belirleyebilmesi ve Başlangıç Satırı Dizini ile En Fazla Satır değerlerini BLL'ye doğru şekilde geçirebilmesi için ObjectDataSource'u da yapılandırmamız gerekir.
Özel disk belleği uygulamak için bir dizi adım gerekir ve varsayılan disk belleği kadar basit olmasa da, yeterli miktarda veri üzerinden disk belleği yapılırken özel disk belleği bir zorunluluktur. İncelenen sonuçlarda gösterildiği gibi, özel disk belleği ASP.NET sayfa işleme süresinden saniyeler ayırabilir ve veritabanı sunucusundaki yükü bir veya daha fazla büyüklük sırasına göre hafifletebilir.
Mutlu Programlama!
Yazar hakkında
Yedi ASP/ASP.NET kitabının yazarı ve 4GuysFromRolla.com kurucusu Scott Mitchell, 1998'den beri Microsoft Web teknolojileriyle çalışmaktadır. Scott bağımsız bir danışman, eğitmen ve yazar olarak çalışmaktadır. Son kitabı Sams Teach Yourself ASP.NET 24 Saat içinde 2.0. Adresine adresinden veya adresinden ulaşabileceğiniz http://ScottOnWriting.NETblogu aracılığıyla ulaşabilirsinizmitchell@4GuysFromRolla.com.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin