Özel Sayfalanmış Verileri Sıralama (C#)

tarafından Scott Mitchell

PDF’yi İndir

Ö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-SQL CASE 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ı GetProductsPagedAndSortedyeni 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(100bir 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 ProductIDsı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 , @startRowIndexve @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_executesqlyürütülür.

Bu saklı yordamı , @startRowIndexve @maximumRows parametreleri için farklı değerlerle test etmek için @sortExpressionbiraz 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.

Saklı Yordamın Üç Giriş Parametresi için Farklı Değerler Deneyin

Şekil 1: Saklı Yordamın Üç Giriş Parametresi için Farklı Değerler Deneyin

Saklı Yordamın Sonuçları Çıkış Penceresinde Gösterilir

Ş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 ProductsTableAdapterve 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: GetProductsPagedAndSortedbu örnekte. Yeni TableAdapter yönteminin mevcut saklı yordamı kullanmasını istediğinizi belirterek başlayın.

Mevcut Saklı Yordamı Kullanmayı Seçme

Ş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 .

GetProductsPagedAndSorted Saklı Yordamını Kullanma

Ş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.

Saklı Yordamın Tablosal Veri Döndürdüğünü Belirtme

Şekil 5: Saklı Yordamın Tablo verileri döndürdüğünü belirtme

Son olarak, sırasıyla ve GetProductsPagedAndSortedyöntemlerini adlandırarak hem DataTable Doldurma hem de DataTable Döndürme desenlerini kullanan DAL yöntemleri FillPagedAndSorted oluşturun.

Yöntem Adlarını Seçin

Ş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, startRowIndexve 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 GetProductsPagedGetProductsPagedAndSorteddeğ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 SelectMethodgeçirmeye çalışır. Özellikle, ObjectDataSource adı özelliğin değerine eşit olan bir giriş parametresi arar SortParameterName . BLL GetProductsPagedAndSorted yönteminde adlı sortExpressionsı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:

  1. GridView, özelliğini üst bilgi bağlantısına tıklanan alanın değeriyle SortExpression güncelleştirir SortExpression
  2. ObjectDataSource, BLL s GetProductsPagedAndSorted yöntemini çağırır ve GridView s SortExpression özelliğini yöntemin sortExpression giriş parametresinin değeri olarak geçirir (uygun startRowIndex ve maximumRows giriş parametresi değerleriyle birlikte)
  3. BLL, DAL yöntemini GetProductsPagedAndSorted çağırır
  4. DAL saklı yordamı yürütür GetProductsPagedAndSorted ve parametresini @sortExpression geçirir (ve @maximumRows giriş parametresi değerleriyle @startRowIndex birlikte)
  5. 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.

Sonuçlar UnitPrice Ölçütüne Göre Sıralanır

Ş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).

Sonuçları Sağlayıcıya Göre Sıralama Denemesi Aşağıdaki Çalışma Zamanı Özel Durumuyla Sonuçlanır

Ş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 SupplierNamebu ö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 SupplierNamediğ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.

SupplierName BoundField s SortExpression değerini CompanyName olarak değiştirin

Şekil 9: SupplierName BoundField s SortExpression değerini CompanyName olarak değiştirme

Sonuçlar Artık Sağlayıcıya Göre Sıralanabilir

Ş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 SelectMethodgeç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.