Özel Sayfalanmış Verileri Sıralama (C#)
tarafından Scott Mitchell
Önceki öğreticide, bir web sayfasında veri sunarken özel disk belleği uygulamayı öğrendik. Bu öğreticide, önceki örneği özel sayfalama sıralama desteğini içerecek şekilde genişletmeyi göreceğiz.
Giriş
Varsayılan disk belleğiyle karşılaştırıldığında, özel disk belleği, çeşitli büyüklük sıralarıyla veriler üzerinden disk belleği performansını geliştirebilir ve bu da büyük miktarlarda verilerde disk belleği yapılırken özel disk belleğinin fiili disk belleği uygulama seçimi olmasını sağlar. Özel disk belleği uygulamak, özellikle de karmaya sıralama eklerken varsayılan disk belleği uygulamaktan daha önemlidir. Bu öğreticide, sıralama ve özel sayfalama desteğini içerecek şekilde örneği önceki örnekten genişleteceğiz.
Not
Bu öğretici bir önceki öğreticiyi temel alarak derlediğinden, başlamadan önce önceki öğreticinin web sayfasından (EfficientPaging.aspx
) öğesi içindeki <asp:Content>
bildirim temelli söz dizimini kopyalayıp sayfadaki öğesinin <asp:Content>
SortParameter.aspx
arasına yapıştırın. Bir ASP.NET sayfasının işlevselliğini diğerine çoğaltma hakkında daha ayrıntılı bir tartışma için , Düzenleme ve Arabirim Ekleme öğreticisine Doğrulama Denetimleri Ekleme öğreticisinin 1. Adımına geri bakın.
1. Adım: Özel Disk Belleği Tekniğini Yeniden İfade Etme
Özel disk belleğinin düzgün çalışması için, Başlangıç Satırı Dizini ve En Fazla Satır parametreleri göz önüne alındığında kayıtların belirli bir alt kümesini verimli bir şekilde alabilen bazı teknikler uygulamamız gerekir. Bu amaca ulaşmak için kullanılabilecek bir dizi teknik vardır. Önceki öğreticide, Microsoft SQL Server 2005'in yeni ROW_NUMBER()
derecelendirme işlevini kullanarak bunu gerçekleştirmeyi inceledik. Kısacası derecelendirme işlevi, ROW_NUMBER()
belirtilen sıralama düzenine göre derecelenmiş bir sorgu tarafından döndürülen her satıra bir satır numarası atar. Daha sonra, numaralandırılmış sonuçların belirli bir bölümü döndürülerek uygun kayıt alt kümesi elde edilir. Aşağıdaki sorguda, alfabetik olarak sıralanan sonuçları alfabetik olarak sıralarken 11 ile 20 arasında numaralı ürünleri döndürmek için bu tekniğin nasıl kullanılacağı gösterilmektedir ProductName
:
SELECT ProductID, ProductName, ...
FROM
(SELECT ProductID, ProductName, ..., ROW_NUMBER() OVER
(ORDER BY ProductName) AS RowRank
FROM Products) AS ProductsWithRowNumbers
WHERE RowRank > 10 AND RowRank <= 20
Bu teknik, belirli bir sıralama düzenini (ProductName
bu örnekte alfabetik olarak sıralanmış) kullanarak sayfalama için iyi çalışır, ancak sonuçların farklı bir sıralama ifadesine göre sıralanmış şekilde gösterilmesi için sorgunun değiştirilmesi gerekir. İdeal olan, yukarıdaki sorgunun yan tümcesinde OVER
bir parametre kullanmak için yeniden yazılmasıdır, örneğin:
SELECT ProductID, ProductName, ...
FROM
(SELECT ProductID, ProductName, ..., ROW_NUMBER() OVER
(ORDER BY @sortExpression) AS RowRank
FROM Products) AS ProductsWithRowNumbers
WHERE RowRank > 10 AND RowRank <= 20
Ne yazık ki parametreli ORDER BY
yan tümcelere izin verilmez. Bunun yerine, bir giriş parametresi kabul eden ancak aşağıdaki geçici çözümlerden birini kullanan bir @sortExpression
saklı yordam oluşturmamız gerekir:
- Kullanılabilecek sıralama ifadelerinin her biri için sabit kodlanmış sorgular yazın; ardından, yürütülecek sorguyu belirlemek için T-SQL deyimlerini kullanın
IF/ELSE
. - n giriş parametresini temel alan dinamik ifadeler sağlamak için deyimini
CASE
kullanın; daha fazla bilgi için T-SQLCASE
Deyimleri'ndeki Sorgu Sonuçlarını Dinamik Olarak Sıralamak için Kullanılır bölümüne bakın.ORDER BY
@sortExpressio
- Saklı yordamda uygun sorguyu bir dize olarak oluşturun ve ardından dinamik sorguyu
sp_executesql
yürütmek için sistem saklı yordamını kullanın.
Bu geçici çözümlerin her birinin bazı dezavantajları vardır. İlk seçenek, her olası sıralama ifadesi için bir sorgu oluşturmanızı gerektirdiğinden diğer ikisi kadar korunamaz. Bu nedenle, daha sonra GridView'a yeni, sıralanabilir alanlar eklemeye karar verirseniz, geri dönüp saklı yordamı güncelleştirmeniz de gerekir. İkinci yaklaşım, dize olmayan veritabanı sütunlarına göre sıralama yaparken performans sorunlarına neden olan bazı inceliklere sahiptir ve ayrıca ilk yaklaşımla aynı bakım sorunlarından muzdariptir. Dinamik SQL kullanan üçüncü seçenek ise, bir saldırganın kendi seçtiği giriş parametresi değerlerini geçirerek saklı yordamı yürütebilmesi durumunda SQL ekleme saldırısı riskini ortaya atar.
Bu yaklaşımların hiçbiri mükemmel olmasa da, üçüncü seçeneğin üçünün en iyisi olduğunu düşünüyorum. Dinamik SQL kullanımıyla, diğer ikisinin sunmadığı bir esneklik düzeyi sunar. Ayrıca, SQL ekleme saldırısı yalnızca bir saldırganın kendi seçtiği giriş parametrelerini geçirerek saklı yordamı yürütebilmesi durumunda kötüye kullanılabilir. DAL parametreli sorgular kullandığından, ADO.NET mimari aracılığıyla veritabanına gönderilen bu parametreleri korur; başka bir deyişle SQL ekleme saldırısı güvenlik açığı yalnızca saldırganın saklı yordamı doğrudan yürütebildiği durumda vardır.
Bu işlevi uygulamak için, Northwind veritabanında adlı GetProductsPagedAndSorted
yeni bir saklı yordam oluşturun. Bu saklı yordam üç giriş parametresini kabul etmelidir: @sortExpression
, sonuçların nasıl sıralanacağını belirten ve yan tümcedeki @startRowIndex
metnin hemen arkasına ORDER BY
eklendiğini belirten türünde nvarchar(100
bir giriş parametresi ve ve @maximumRows
önceki öğreticide OVER
incelenen saklı yordamdan GetProductsPaged
aynı iki tamsayı giriş parametresi. GetProductsPagedAndSorted
Aşağıdaki betiği kullanarak saklı yordamı oluşturun:
CREATE PROCEDURE dbo.GetProductsPagedAndSorted
(
@sortExpression nvarchar(100),
@startRowIndex int,
@maximumRows int
)
AS
-- Make sure a @sortExpression is specified
IF LEN(@sortExpression) = 0
SET @sortExpression = 'ProductID'
-- Issue query
DECLARE @sql nvarchar(4000)
SET @sql = 'SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit,
UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued,
CategoryName, SupplierName
FROM (SELECT ProductID, ProductName, p.SupplierID, p.CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued,
c.CategoryName, s.CompanyName AS SupplierName,
ROW_NUMBER() OVER (ORDER BY ' + @sortExpression + ') AS RowRank
FROM Products AS p
INNER JOIN Categories AS c ON
c.CategoryID = p.CategoryID
INNER JOIN Suppliers AS s ON
s.SupplierID = p.SupplierID) AS ProductsWithRowNumbers
WHERE RowRank > ' + CONVERT(nvarchar(10), @startRowIndex) +
' AND RowRank <= (' + CONVERT(nvarchar(10), @startRowIndex) + ' + '
+ CONVERT(nvarchar(10), @maximumRows) + ')'
-- Execute the SQL query
EXEC sp_executesql @sql
Saklı yordam, parametre için bir değerin belirtildiğinden @sortExpression
emin olarak başlar. Eksikse, sonuçlar ölçütüne göre ProductID
sıralanır. Ardından dinamik SQL sorgusu oluşturulur. Buradaki dinamik SQL sorgusunun Products tablosundaki tüm satırları almak için kullanılan önceki sorgularımızdan biraz farklı olduğunu unutmayın. Önceki örneklerde, alt sorgu kullanarak her ürünün ilişkili kategorilerini ve sağlayıcı adlarını elde ettik. Bu karar Veri Erişim Katmanı Oluşturma öğreticisinde geri alındı ve TableAdapter bu tür sorgular için ilişkili ekleme, güncelleştirme ve silme yöntemlerini otomatik olarak oluşturamadığından, s yerine JOIN
yapıldı. Ancak, sonuçların GetProductsPagedAndSorted
kategoriye veya sağlayıcı adlarına göre sıralanması için saklı yordamın s kullanması JOIN
gerekir.
Bu dinamik sorgu, statik sorgu bölümleri ile , @startRowIndex
ve @sortExpression
@maximumRows
parametreleri birleştirilerek oluşturulur. ve @maximumRows
tamsayı parametreleri olduğundan@startRowIndex
, doğru bir şekilde birleştirilebilmesi için nvarchars'a dönüştürülmeleri gerekir. Bu dinamik SQL sorgusu oluşturulduktan sonra aracılığıyla sp_executesql
yürütülür.
Bu saklı yordamı , @startRowIndex
ve @maximumRows
parametreleri için farklı değerlerle test etmek için @sortExpression
biraz zaman ayırın. Sunucu Gezgini'nden saklı yordam adına sağ tıklayın ve Yürüt'e tıklayın. Bu, giriş parametrelerini girebileceğiniz Saklı Yordamı Çalıştır iletişim kutusunu açar (bkz. Şekil 1). Sonuçları kategori adına göre sıralamak için parametre değeri olarak CategoryName kullanın; sağlayıcının şirket adına göre sıralamak için @sortExpression
CompanyName kullanın. Parametre değerlerini sağladıktan sonra Tamam'a tıklayın. Sonuçlar Çıkış penceresinde görüntülenir. Şekil 2'de, azalan düzende sıralama yaparken 11 ile 20 arasında derecelenmiş ürünler döndürülirken elde UnitPrice
edilen sonuçlar gösterilir.
Şekil 1: Saklı Yordamın Üç Giriş Parametresi için Farklı Değerler Deneyin
Şekil 2: Saklı Yordamın Sonuçları Çıkış Penceresinde Gösterilir (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Not
Sonuçları yan tümcesinde OVER
belirtilen ORDER BY
sütuna göre sıralarken, SQL Server sonuçları sıralamalıdır. 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 sorguların performansını artırmak için, sonuçların sıralandığı sütun için kümelenmemiş bir dizin eklemeyi göz önünde bulundurun. Daha fazla ayrıntı için SQL Server 2005'te Derecelendirme İşlevleri ve Performansı'na bakın.
2. Adım: Veri Erişimi ve İş Mantığı Katmanlarını Artırma
GetProductsPagedAndSorted
Saklı yordam oluşturulduktan sonraki adımımız, uygulama mimarimiz aracılığıyla bu saklı yordamı yürütmek için bir yol sağlamaktır. Bu, hem DAL hem de BLL'ye uygun bir yöntem eklemeyi gerektirir. DAL'ye bir yöntem ekleyerek başlayalım. Yazılan Veri Kümesi'ni Northwind.xsd
açın, öğesine sağ tıklayın ProductsTableAdapter
ve bağlam menüsünden Sorgu Ekle seçeneğini belirleyin. Önceki öğreticide yaptığımız gibi, bu yeni DAL yöntemini mevcut saklı yordamını kullanacak şekilde yapılandırmak istiyoruz: GetProductsPagedAndSorted
bu örnekte. Yeni TableAdapter yönteminin mevcut saklı yordamı kullanmasını istediğinizi belirterek başlayın.
Şekil 3: Mevcut Saklı Yordamı Kullanmayı Seçme
Kullanılacak saklı yordamı belirtmek için sonraki ekranda açılan listeden saklı yordamı seçin GetProductsPagedAndSorted
.
Şekil 4: GetProductsPagedAndSorted Saklı Yordamını Kullanma
Bu saklı yordam, sonuçları olarak bir kayıt kümesi döndürür, bu nedenle sonraki ekranda tablosal veriler döndürdüğünü gösterir.
Şekil 5: Saklı Yordamın Tablo verileri döndürdüğünü belirtme
Son olarak, sırasıyla ve GetProductsPagedAndSorted
yöntemlerini adlandırarak hem DataTable Doldurma hem de DataTable Döndürme desenlerini kullanan DAL yöntemleri FillPagedAndSorted
oluşturun.
Şekil 6: Yöntem Adlarını Seçme
DAL'yi genişlettik, BLL'ye dönmek için hazırız. ProductsBLL
sınıf dosyasını açın ve yeni bir yöntem ekleyin: GetProductsPagedAndSorted
. Bu yöntemin üç giriş parametresi sortExpression
, startRowIndex
ve maximumRows
kabul etmesi gerekir ve dal GetProductsPagedAndSorted
yöntemine çağrı yapmalıdır, örneğin:
[System.ComponentModel.DataObjectMethodAttribute(
System.ComponentModel.DataObjectMethodType.Select, false)]
public Northwind.ProductsDataTable GetProductsPagedAndSorted(
string sortExpression, int startRowIndex, int maximumRows)
{
return Adapter.GetProductsPagedAndSorted
(sortExpression, startRowIndex, maximumRows);
}
3. Adım: SortExpression Parametresini Geçirmek için ObjectDataSource'un Yapılandırılması
DAL ve BLL'yi saklı yordamı kullanan GetProductsPagedAndSorted
yöntemleri içerecek şekilde genişleten tek şey, sayfadaki ObjectDataSource'u SortParameter.aspx
yeni BLL yöntemini kullanacak şekilde yapılandırmak ve parametreyi SortExpression
kullanıcının sonuçları sıralamak için istediği sütuna göre geçirmektir.
ObjectDataSource'un SelectMethod
değerini olarak GetProductsPaged
GetProductsPagedAndSorted
değiştirerek başlayın. Bu işlem Veri Kaynağını Yapılandırma sihirbazı, Özellikler penceresi veya doğrudan bildirim temelli söz dizimi aracılığıyla yapılabilir. Ardından, ObjectDataSource SortParameterName
özelliği için bir değer sağlamamız gerekir. Bu özellik ayarlanırsa, ObjectDataSource GridView s SortExpression
özelliğini öğesine SelectMethod
geçirmeye çalışır. Özellikle, ObjectDataSource adı özelliğin değerine eşit olan bir giriş parametresi arar SortParameterName
. BLL GetProductsPagedAndSorted
yönteminde adlı sortExpression
sıralama ifadesi giriş parametresi bulunduğundan ObjectDataSource'un SortExpression
özelliğini sortExpression olarak ayarlayın.
Bu iki değişikliği yaptıktan sonra ObjectDataSource bildirim temelli söz dizimi aşağıdakine benzer olmalıdır:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
SelectMethod="GetProductsPagedAndSorted" EnablePaging="True"
SelectCountMethod="TotalNumberOfProducts" SortParameterName="sortExpression">
</asp:ObjectDataSource>
Not
Önceki öğreticide olduğu gibi, ObjectDataSource'un SelectParameters koleksiyonunda sortExpression, startRowIndex veya maximumRows giriş parametrelerini içermediğinden emin olun.
GridView'da sıralamayı etkinleştirmek için GridView s özelliğini true
olarak ayarlayan ve her sütun için üst bilgi metninin LinkButton olarak işlenmesine neden olan GridView akıllı AllowSorting
etiketinde Sıralamayı Etkinleştir onay kutusunu işaretlemeniz yeterlidir. Son kullanıcı LinkButtons üst bilgilerinden birine tıkladığında geri gönderme işlemi gerçekleştirilir ve aşağıdaki adımlar geçici olarak gerçekleştirilir:
- GridView, özelliğini üst bilgi bağlantısına tıklanan alanın değeriyle
SortExpression
güncelleştirirSortExpression
- ObjectDataSource, BLL s
GetProductsPagedAndSorted
yöntemini çağırır ve GridView sSortExpression
özelliğini yönteminsortExpression
giriş parametresinin değeri olarak geçirir (uygunstartRowIndex
vemaximumRows
giriş parametresi değerleriyle birlikte) - BLL, DAL yöntemini
GetProductsPagedAndSorted
çağırır - DAL saklı yordamı yürütür
GetProductsPagedAndSorted
ve parametresini@sortExpression
geçirir (ve@maximumRows
giriş parametresi değerleriyle@startRowIndex
birlikte) - Saklı yordam, verilerin uygun alt kümesini BLL'ye döndürür ve bu alt kümesini ObjectDataSource'a döndürür; Bu veriler daha sonra GridView'a bağlanır, HTML olarak işlenir ve son kullanıcıya gönderilir
Şekil 7'de, artan düzende sıralandığında sonuçların UnitPrice
ilk sayfası gösterilir.
Şekil 7: Sonuçlar BirimFiyatına Göre Sıralanır (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Geçerli uygulama sonuçları ürün adına, kategori adına, birim başına miktara ve birim fiyatına göre doğru şekilde sıralayabilir ancak sonuçları sağlayıcı adına göre sıralamaya çalışmak çalışma zamanı özel durumuyla sonuçlanır (bkz. Şekil 8).
Şekil 8: Sonuçları Sağlayıcıya Göre Sıralama Girişimi Aşağıdaki Çalışma Zamanı Özel Durumuyla Sonuçlanır
GridView'un SupplierName
BoundField değeri olarak ayarlandığından SupplierName
bu özel durum oluşurSortExpression
. Ancak, tablodaki Suppliers
sağlayıcının adı aslında olarak adlandırılır CompanyName
. Bu sütun adı olarak SupplierName
diğer adla adlandırıldık. Ancak işlev OVER
tarafından ROW_NUMBER()
kullanılan yan tümcesi diğer adı kullanamaz ve gerçek sütun adını kullanmalıdır. Bu nedenle, BoundField s SortExpression
değerini SupplierName yerine CompanyName olarak değiştirin SupplierName
(bkz. Şekil 9). Şekil 10'da gösterildiği gibi, bu değişiklik sonrasında sonuçlar sağlayıcıya göre sıralanabilir.
Şekil 9: SupplierName BoundField s SortExpression değerini CompanyName olarak değiştirme
Şekil 10: Sonuçlar Artık Sağlayıcıya Göre Sıralanabilir (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Özet
Önceki öğreticide incelediğimiz özel disk belleği uygulaması, sonuçların sıralama sırasının tasarım zamanında belirtilmesi gerekti. Kısacası bu, uyguladığımız özel disk belleği uygulamasının aynı zamanda sıralama özellikleri sağlayamadığı anlamına geliyordu. Bu öğreticide, saklı yordamı ilkinden sonuçların sıralanabileceği bir @sortExpression
giriş parametresi içerecek şekilde genişleterek bu sınırlamayı aşacağız.
Bu saklı yordamı oluşturduktan ve DAL ve BLL'de yeni yöntemler oluşturduktan sonra, ObjectDataSource'un GridView geçerli SortExpression
özelliğini BLL'ye SelectMethod
geçirecek şekilde yapılandırarak hem sıralama hem de özel disk belleği sunan bir GridView uygulayabildik.
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.
Özel Teşekkürler
Bu öğretici serisi birçok yararlı gözden geçiren tarafından gözden geçirildi. Bu öğreticinin baş gözden geçireni Carlos Santos'tu. Yaklaşan MSDN makalelerimi gözden geçirmek istiyor musunuz? Öyleyse, bana bir satır mitchell@4GuysFromRolla.combırakın.