Aracılığıyla paylaş


Büyük Miktarlı Verileri Etkili Bir Şekilde Sayfalama (VB)

tarafından Scott Mitchell

PDF'i indirin

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.

Geçici SQL Deyimi Kullanma

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

Sorguyu Tek Bir Değer Döndüren BIR SELECT Deyimi Kullanacak Şekilde Yapılandırma

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

SELECT COUNT(*) FROM Ürünler Sorgusunu Kullanma

Şekil 3: SELECT COUNT(*) FROM Products Sorgusunu Kullanma

Son olarak, yönteminin adını belirtin. Yukarıda belirtildiği gibi, komutunu kullanalım TotalNumberOfProducts.

DAL Yöntemini TotalNumberOfProducts olarak adlandırın

Ş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 NULLelde 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 Server SET 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 (ancak ROW_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ığıyla IDENTITY ) ilişkilendirilir. Tablo değişkeni doldurulduktan sonra, temel tabloyla birleştirilen tablo değişkenindeki bir SELECT deyim yürütülerek belirli kayıtların çekilmesi gerçekleştirilebilir. deyimi SET 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.

Döndürülen Her Kayıt için Fiyat Sırası Dahil Edildi

Ş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 (UnitPriceyukarı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 + MaximumRowsolan 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).

Ürünler Aracılığıyla Sayfalama için Yeni Bir Saklı Yordam Ekleme

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

<span sınıfı= için bir Değer girin@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.

Verilerin İkinci Sayfasında Görüntülenecek Kayıtlar Döndürülür

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

Mevcut Saklı Yordamı Kullanarak DAL Yöntemini Oluşturma

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

Açılan Listeden GetProductsPaged Saklı Yordamını 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.

Saklı Yordamın 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 Doldurma hem de DataTable Döndürme'yi kullanarak yöntemler oluşturun. İlk yöntemi ve ikincisini FillPaged GetProductsPagedolarak adlandırın.

FillPaged ve GetProductsPaged Yöntemlerini 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.

ObjectDataSource'ı ProductsBLL Sınıfının GetProductsPaged Yöntemini Kullanacak Şekilde Yapılandırma

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

Giriş Parametresi Kaynaklarını Yok olarak bırakı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, , CategoryNameSupplierName, QuantityPerUnitve 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.

GridView Görüntülenmiyor

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

  1. ObjectDataSource s EnablePaging özelliğinitrue, ObjectDataSource'a iki ek parametreye SelectMethod 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).
  2. ObjectDataSource s StartRowIndexParameterName ve MaximumRowsParameterName Özelliklerini buna göre StartRowIndexParameterName ayarlayın ve MaximumRowsParameterName özellikleri, özel disk belleği amacıyla içine geçirilen giriş parametrelerinin SelectMethod adlarını gösterir. Varsayılan olarak, bu parametre adları ve maximumRowsşeklindedirstartIndexRow. Bu nedenle, BLL'de yöntemi oluştururken GetProductsPaged giriş parametreleri için bu değerleri kullandım. ve gibi startIndex maxRowsBLL s GetProductsPaged yöntemi için farklı parametre adları kullanmayı seçtiyseniz, objectDataSource s StartRowIndexParameterName ve MaximumRowsParameterName özelliklerini buna göre ayarlamanız gerekir (örneğin, için StartRowIndexParameterName startIndex ve maxRows MaximumRowsParameterName).
  3. 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 s TotalNumberOfProducts yönteminin ProductsBLL sorguyu yürüten SELECT 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.
  4. startRowIndex Sihirbaz aracılığıyla ObjectDataSource yapılandırırken ObjectDataSource Bildirim İşaretlemesinden ve<asp:Parameter> maximumRowsÖğelerini kaldırın; Visual Studio yöntemin GetProductsPaged giriş parametreleri için otomatik olarak iki <asp:Parameter> öğe ekledi. ayarıyla EnablePaging 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önteme GetProductsPaged iki parametre geçirmeyi TotalNumberOfProducts 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.

Özel Disk Belleği Kullanmak için ObjectDataSource Denetimini Yapılandırın

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

Ürün Adına Göre Sıralanmış Veriler, Özel Sayfalama Kullanılarak Sayfalanır

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

Yalnızca Geçerli Sayfada Gösterilen Veriler Sıralanı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ı PageIndexuygun ş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:

  1. Kaydı silme
  2. Belirtilen PageIndex ve için görüntülenecek uygun kayıtları alın PageSize
  3. öğesinin PageIndex veri kaynağındaki veri sayfa sayısını aşmadığından emin olun; aşıyorsa GridView s PageIndex özelliğini otomatik olarak azaltma
  4. 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 PageIndexazaltmamı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 nullemin 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