Büyük Miktarlı Verileri Etkili Bir Şekilde Sayfalama (VB)
tarafından Scott Mitchell
Veri sunusu denetiminin varsayılan disk belleği 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ı etiketinde Sayfalandırmayı 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 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 uygulamak için varsayılan disk belleğinden biraz daha fazla çaba gerekir
Uygulama kolaylığı nedeniyle bir onay kutusunu işaretlemeniz yeter ve işiniz bitti! varsayılan sayfalama cazip bir seçenektir. Ancak tüm kayıtların alınmasındaki saf yaklaşımı, yeterince büyük miktarda veriyi veya çok sayıda eşzamanlı kullanıcısı olan siteleri sayfalarken bunu olanaksı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, sonuçları sıralamak 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ıza olanak tanır. Bu öğreticide, 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 sayfalama 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 siparişler olabilir.
Not
Özel disk belleği tarafından sergilenen tam performans kazancı, sayfalandırılan kayıtların toplam sayısına ve veritabanı sunucusuna yerleştirilen 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 ürünlerle ilgilenirdik ve bu şekilde devam ederdik.
Hangi kayıtların alınması gerektiğini ve disk belleği arabiriminin nasıl işlenmesi gerektiğini belirten üç değişken vardır:
- Başlangıç Satırı Dizini görüntülenecek veri sayfasındaki ilk satırın dizinidir; 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 disk belleği yaparken Başlangıç Satırı Dizini 0 * 10 + 1 veya 1 olur; İkinci 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. Bu değişken en fazla satır olarak adlandırılır çünkü son sayfada sayfa boyutundan daha az kayıt döndürülebilir. Örneğin, sayfa başına 81 ürün 10 kaydı sayfalandığında, 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 Sayfalanan kayıtların toplam sayısını gösterir. Belirli bir sayfa için hangi kayıtların alındığını belirlemek için bu değişken gerekli olmasa da, disk belleği arabirimini dikte eder. Örneğin, disk belleğine alınan 81 ürün varsa, disk belleği arabirimi disk belleği kullanıcı arabiriminde dokuz sayfa numarası görüntülemeyi bilir.
Varsayılan sayfalamada, Başlangıç Satırı Dizini sayfa dizininin ürünü ve sayfa boyutu artı bir olarak hesaplanırken, En Fazla Satır Sayısı yalnızca sayfa boyutudur. Varsayılan disk belleği, herhangi bir veri sayfası işlenirken veritabanındaki tüm kayıtları aldığından, her satırın dizini bilinir ve böylece Başlangıç Satırı Dizini satırına geçiş önemsiz bir görev haline gelir. Ayrıca, Yalnızca DataTable'daki kayıt 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üne alındığında, ö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ı sayısını 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 toplam kayıt 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ılarak COUNT
elde edilebilir. Örneğin, tablodaki toplam kayıt Products
sayısını 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 klasöründeki Northwind.xsd
Typed DataSet dosyasını App_Code/DAL
açın. Ardından Tasarımcı'da öğesine ProductsTableAdapter
sağ tıklayın 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, tablodaki Products
toplam kayıt sayısı olan skaler değer, tekil değer seçeneğini döndüren öğesini seçer 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 Products 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 sorgusundan NULL
elde edilen sonucun olması durumunda DAL içindeki 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
yöntemine yalnızca aşağı çağıran 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ğlamalıyı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ğeri olan 0 değerini döndürür.
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 ve uygun kayıtları döndüren yöntemler oluşturmaktır. Bunu gerçekleştirmeden önce gerekli SQL betiğine göz atalım. Karşımıza çıkan zorluk, yalnızca Başlangıç Satırı Dizini'nde (ve Kayıt Sayısı Üst Sınırı sayısına kadar) yalnızca bu kayıtları döndürebilmemiz için, sayfalanan sonuçların tamamında her satıra verimli bir şekilde dizin atayabilmemiz gerektiğidir.
Veritabanı tablosunda satır dizini görevi görecek bir sütun zaten 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ı geçersiz hale getirir.
Satır dizinini sayfalanacak verilerle verimli bir şekilde ilişkilendirmek ve böylece kayıtların kesin alt kümesinin alınmasını sağlamak için kullanılan iki genel teknik vardır:
SQL Server 2005'e
ROW_NUMBER()
yeni eklenen SQL Server 2005 anahtar sözcüğünüROW_NUMBER()
kullanarak anahtar sözcük, döndürülen her kayıtla bir sıralamayı bazı sıralamaya göre ilişkilendirir. Bu sıralama, her satır için satır dizini olarak kullanılabilir.Bir sorguyu sonlandırmadan önce kaç toplam kaydın işlenmesi gerektiğini belirtmek için Tablo Değişkeni ve
SET ROWCOUNT
SQL ServerSET ROWCOUNT
deyimini kullanma;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 sütunu ve sütunları olan 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, temel tabloyla birleştirilen tablo değişkenindeki birSELECT
deyim yürütülerek belirli kayıtların çekilmesi gerçekleştirilebilir. deyimiSET ROWCOUNT
, 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 ve En Fazla Satır sayısı atanır. Verilerin ilk birkaç sayfası gibi düşük numaralı sayfalarda sayfalama yaparken bu yaklaşım çok verimlidir. Ancak, sonuna yakın bir sayfa alını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 dizimi kullanılarak belirli bir sıralama üzerinden döndürülen her kayıtla bir derecelendirmeyle 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 Sırası Dahil Edildi
Not
ROW_NUMBER()
, SQL Server 2005'te kullanılabilen 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ıralamalıdır. Sonuçların sıralandığı sütunlarda 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, türetilmiş bir tablo sonucu döndürmek ROW_NUMBER()
için kullanılabilir ve bu da yan tümcesinde WHERE
görünebilir. Ö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ümcesi 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 öğreticide daha sonra göreceğimiz gibi, StartRowIndex
ObjectDataSource tarafından sağlanan dizin sıfırdan başlarken ROW_NUMBER()
, SQL Server 2005 tarafından döndürülen değer 1'den başlayarak dizine eklenir. Bu nedenle, yan tümcesi WHERE
kesinlikle değerinden StartRowIndex
büyük ve 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 tartıştığı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; ürünleri alfabetik olarak adlarına göre sıralayalım. Bu, bu öğreticideki özel disk belleği uygulamasıyla sıralanabilir durumdan daha özel bir sayfalandırılmış rapor oluşturamayacağımız anlamına gelir. 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şturmalıyız. 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 Sayfalama için Yeni Bir Saklı Yordam Ekleme
Bu saklı yordam iki tamsayı giriş parametresini @startRowIndex
kabul etmelidir ve @maximumRows
yalnızca belirtilenden büyük ve belirtilenden @startRowIndex
küçük veya buna eşit + @startRowIndex
@maximumRow
satırları döndürerek alan tarafından ProductName
sıralanmış işlevini kullanmalıdır.ROW_NUMBER()
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 bir dakikanızı 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.
@startRowIndex ve @maximumRows Parametreler" />
Şekil 7: ve @maximumRows Parametreleri için @startRowIndex bir Değer girin
Bu giriş parametreleri değerlerini seçtikten sonra Çıkış penceresi sonuçları gösterir. Şekil 8'de hem hem @maximumRows
de parametreleri için 10 geçirildiğinde eldeki @startRowIndex
sonuçlar gösterilmektedir.
Şekil 8: İkinci Veri Sayfasında Görünecek 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
açın, öğesine ProductsTableAdapter
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: Açılan Listeden GetProductsPaged Saklı Yordamını Seçin
Sonraki ekranda saklı yordam tarafından ne tür verilerin döndürüldiği sorılır: tablosal veriler, tek bir değer veya değer yok. GetProductsPaged
Saklı yordam birden çok kayıt döndürebildiğinden, tablosal veriler döndürdüğünü gösterir.
Ş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 Doldurma hem de DataTable Döndürme'yi kullanarak yöntemler oluşturun. İlk yöntemi ve ikincisini FillPaged
GetProductsPaged
olarak adlandırın.
Şekil 12: FillPaged ve GetProductsPaged Yöntemlerini 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 En Fazla Satır belirtme 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, bu yöntemi kullanmak üzere bir ObjectDataSource yapılandırırken kullanmayı startRowIndex
maximumRows
seçip bizi fazladan bir iş bitinden 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ıktan sonra, özel disk belleği kullanarak temel alınan kayıtlarda sayfalanan bir GridView denetimi oluşturmaya hazırız. Klasördeki PagingAndSorting
sayfayı EfficientPaging.aspx
açarak başlayı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'un ProductsBLL Sınıfının GetProductsPaged Yöntemini Kullanacak Şekilde Yapılandırılması
Salt okunur bir GridView oluşturduğumuz için, INSERT, UPDATE ve DELETE sekmelerindeki yöntem açılan listesini (Yok) olarak ayarlamak için bir dakikanızı ayırın.
Ardından, ObjectDataSource sihirbazı yöntem s startRowIndex
ve maximumRows
giriş parametreleri değerlerinin GetProductsPaged
kaynaklarını ister. Bu giriş parametreleri aslında GridView tarafından otomatik olarak ayarlanır, bu nedenle kaynak kümesini Yok olarak bırakın ve Son'a tıklayın.
Ş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 ProductName
, , CategoryName
SupplierName
, QuantityPerUnit
ve UnitPrice
BoundField değerlerini görüntülemeyi tercih ettim. Ayrıca, akıllı etiketinde Sayfalandırmayı Etkinleştir onay kutusunu işaretleyerek GridView'ı disk belleğini destekleyecek şekilde yapılandırın. Bu değişikliklerden sonra GridView ve ObjectDataSource bildirim temelli işaretleme aşağıdakine benzer görünmelidir:
<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'un özel disk belleği kullanacak şekilde yapılandırılması gerekir. Bu, aşağıdaki adımlarda gerçekleştirilebilir:
- ObjectDataSource s
EnablePaging
özelliğinitrue
, ObjectDataSource'a iki ek parametreyeSelectMethod
geçirmesi gerektiğini belirten olarak 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 buna göreStartRowIndexParameterName
ayarlayın 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. ve gibistartIndex
maxRows
BLL sGetProductsPaged
yöntemi için farklı parametre adları kullanmayı seçtiyseniz, objectDataSource sStartRowIndexParameterName
veMaximumRowsParameterName
özelliklerini buna göre ayarlamanız gerekir (örneğin, içinStartRowIndexParameterName
startIndex ve maxRowsMaximumRowsParameterName
). - ObjectDataSource s
SelectCountMethod
Özelliğini, Sayfalanan Toplam Kayıt Sayısını Döndüren Yöntemin Adı olarak ayarlayın (TotalNumberOfProducts
), sınıf sTotalNumberOfProducts
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. startRowIndex
Sihirbaz aracılığıyla ObjectDataSource yapılandırırken ObjectDataSource Bildirim İşaretlemesinden ve<asp:Parameter>
maximumRows
Öğelerini kaldırın; Visual Studio yönteminGetProductsPaged
giriş parametreleri için otomatik olarak iki<asp:Parameter>
öğe ekledi. ayarıylaEnablePaging
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öntemi bulamadı: startRowIndex, maximumRows.
Bu değişiklikleri yaptıktan sonra ObjectDataSource 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 tarayıcı üzerinden bu sayfayı ziyaret edin. Alfabetik olarak sıralanmış 10 ürünün listelendiğini görmeniz gerekir. Verilerde adım adım ilerleyerek her seferinde bir sayfa ilerleyin. Varsayılan sayfalama ile özel sayfalama arasındaki son kullanıcı perspektifinden görsel bir fark olmasa da, özel sayfalama yalnızca belirli bir sayfa için görüntülenmesi gereken kayıtları aldığından büyük miktarda veri aracılığıyla 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 sayfalama ile ObjectDataSource SelectCountMethod
tarafından döndürülen sayfa sayısı değeri GridView'un görünüm durumunda depolanır. , EditIndex
, , DataKeys
SelectedIndex
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 PageIndex
belirtir. Son sayfa bağlantısına tıklanırsa, GridView özelliğini özelliğinden bir değere PageCount
atarPageIndex
. Görünüm durumu devre dışı bırakılarak, PageCount
değer geri göndermeler arasında kaybolur ve PageIndex
bunun 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 belirtmiş olabilirsiniz. Ne yazık ki geçerli özel disk belleği uygulamamızla GridView'a sıralama desteği eklemek, kayıtları yalnızca o anda görüntülenen veri sayfasında 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 Tigers gösterilmektedir. Bu, Alfabetik olarak Carnarvon Tigers'ı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 görüntüyü görüntülemek için tıklayın)
Sıralama yalnızca geçerli veri sayfası için geçerlidir çünkü veriler BLL GetProductsPaged
s yönteminden alındıktan sonra sıralama gerçekleşir ve bu yöntem yalnızca belirli sayfa için bu kayıtları döndürür. Sıralamayı doğru uygulamak için, belirli veri sayfasını döndürmeden önce verilerin 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 öğretici için silmeyi etkinleştirin. Bir kerede 81 ürün, 10 ürün arasından disk belleği 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 işlev varsayılan sayfalama ile gösterilir. Ancak özel sayfalama ile, son sayfadaki son ürünü sildikten sonra GridView ekrandan tamamen kaybolur. Bunun olmasının 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. Özel Sayfalama ile Bir GridView'dan Son Sayfadaki Son Kaydı Silme. Özetle, 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
- öğesinin
PageIndex
veri kaynağındaki veri sayfa sayısını aşmadığından emin olun; 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ımda 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
döndürür. 4. Adımda GridView, 2. Adımda alınan verilere bağlanmaya çalışır; ancak 2. Adımda hiçbir kayıt döndürülmedi, bu nedenle boş bir GridView oluştu. Varsayılan sayfalamada, 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 olay RowDeleted
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 s 'yi PageIndex
azaltmamız gerekir. Elbette, yalnızca silme işleminin PageIndex
gerçekten başarılı olup olmadığını güncelleştirmek istiyoruz. Bu, özelliğinin e.Exception
olduğundan null
emin olarak belirlenebilir.
Bu yaklaşım, 1. Adımdan sonraki ama 2. Adımdan öncekini güncelleştirdiğinden PageIndex
çalışır. 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ım'daki kaydı sildikten sonra (ancak 2. Adımda verileri yeniden almadan önce), işlemden bir veya daha fazla satır etkilendiyse GridView ö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 ikisi için de kod, örneğin arka planda kod sınıfında EfficientPaging.aspx
bulunabilir.
Varsayılan ve Özel Disk Belleği 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. Ancak özel disk belleği ne kadar daha verimlidir? Varsayılan disk belleğinden özel disk belleğine geçilerek ne tür performans kazançları görülebilir?
Ne yazık ki, burada tüm yanıtlara uyan bir boyut yoktur. Performans kazancı, bir dizi faktöre bağlıdır; en belirgin ikisi, sayfalanan kayıt 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 arasındaki büyük tablolarda performans farkı yüksektir.
"SQL Server 2005 ile ASP.NET 2.0'da Özel Disk Belleği" makalem, 50.000 kaydı olan 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 sorguyu SQL Server düzeyinde (SQL Profiler kullanarak) hem de ASP.NET izleme özelliklerini kullanarak ASP.NET sayfasında 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.
Ortalama 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 İzlemesi | 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 354 daha az okuma gerekir ve bu sürenin bir bölümünde tamamlanır. ASP.NET sayfasında, özel sayfa varsayılan sayfalama kullanılırken geçen sürenin 1/100'ünde işlenebiliyordu.
Özet
Varsayılan disk belleği, veri Web denetiminin akıllı etiketinde Sayfalama'yı Etkinleştir onay kutusunu işaretlemeniz gerekir 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. Bu performans yüküyle mücadele etmek için ObjectDataSource 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 toplam kayıt sayısını belirlemek için bir araç eklememiz gerekir. Bu DAL ve BLL yöntemlerini oluşturduktan sonra, toplam kaç kaydın disk belleğine alındığını belirleyebilmesi ve Başlangıç Satırı Dizini ve En Fazla Satır değerlerini BLL'ye doğru şekilde geçirebilmesi için ObjectDataSource'un da yapılandırılması gerekir.
Özel disk belleği uygulamak bir dizi adım gerektirir ve varsayılan disk belleği kadar basit olmasa da, yeterli miktarda veriyi sayfalarken ö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 emriyle 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ışır. Son kitabı Sams Teach Yourself ASP.NET 24 Hours 2.0'dır. Adresine adresinden veya adresinden ulaşabileceğiniz blogu aracılığıyla ulaşabilirsinizmitchell@4GuysFromRolla.com.http://ScottOnWriting.NET
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