SQL ROW_NUMBER() Fonksiyonu ile Sayfalama

ASP.NET uygulamalarında veriyi listelerken ihtiyaç duyulan yöntemlerden birisi de sayfalamadır. Özellikle listelenecek veri sayısı yeterince fazla olduğunda sayfalama kaçınılmaz olarak ortaya çıkmaktadır. ASP.NET bu amaçla kullanıcılarına birtakım kontroller üzerinden sayfalama imkanı sunsa da verinin tamamını çekip viewstate üzerinde saklaması dolayısıyla çoğu zaman performans kaybına yol açmaktadır.

Bu noktada SQL ROW_NUMBER() fonksiyonu kullanıcılara kendi geliştirecekleri sayfalama işleminde aynı anda sadece görüntülenecek veriyi seçme imkanı sunmaktadır. SQL ROW_NUMBER() fonsiyonu temel olarak SELECT sorgusu ile elde edilen tabloya 1’den başlayan ve 1’er artarak sıralı bir şekilde devam eden yeni bir kolon ekler.

SQL ROW_NUMBER() fonksiyonu ile yapılacak örnek bir sayfalama işlemi için Northwind veritabanında yer alan Products tablosu kullanılarak aşağıdaki Stored Procedure oluşturulmuştur.

CREATE PROCEDURE [dbo].[SelectProducts]
   @PAGE_SIZE int,
   @PAGE_NUMBER int
AS
   BEGIN
   SET NOCOUNT ON;
      BEGIN
      WITH TEMP as
      (
          SELECT TOP (@PAGE_SIZE*@PAGE_NUMBER+1)
          ROW_NUMBER() OVER (ORDER BY P.ProductID) as RowNumber,
          P.ProductID,
          P.ProductName,
          S.CompanyName,
          C.CategoryName,
          P.QuantityPerUnit,
          P.UnitPrice,
          P.UnitsInStock,
          P.UnitsOnOrder,
          P.ReorderLevel
          FROM dbo.Products P
          JOIN dbo.Categories C on P.CategoryID = C.CategoryID
          JOIN dbo.Suppliers S on P.SupplierID = S.SupplierID
      )
      SELECT    TOP (@PAGE_SIZE*@PAGE_NUMBER+1) *
      FROM TEMP
      WHERE RowNumber between @PAGE_SIZE*(@PAGE_NUMBER-1)+1 and @PAGE_SIZE*@PAGE_NUMBER+1;
      END
END

Yukarıdaki Stored Procedure @PAGE_SIZE ve @PAGE_NUMBER olmak üzere iki parametre almaktadır. Bu parametrelerden @PAGE_SIZE her bir sayfada listelenecek veri sayısını, @PAGE_NUMBER ise listelenmek istenen sayfa numarasını temsil etmektedir. Sorguda dikkat edildiği üzere @PAGE_SIZE+1 adet veri seçilmektedir. Bunun nedeni ise arayüzde bir sonraki sayfanın varlığını kontrol etmektir.

Verilerin listeleneceği web form arayüzü için aşağıdaki yapı kullanılmıştır.

<asp:HiddenField ID="hfPageSize" runat="server" Value="10"/>
<asp:HiddenField ID="hfPageNumber" runat="server" Value="1"/>
<table>
    <tr>
        <td colspan="9" class="main-header">Products</td>
    </tr>
    <tr>
        <td colspan="9" class="paging">
            <asp:LinkButton ID="btPrevious" runat="server" Visible="false" onclick="btPrevious_Click"><< Previous</asp:LinkButton>
            <asp:LinkButton ID="btNext" runat="server" Visible="false" onclick="btNext_Click">Next >></asp:LinkButton>
        </td>
    </tr>
    <tr class="header">
        <td>Product ID</td>
        <td>Product Name</td>
        <td>Company Name</td>
        <td>Category Name</td>
        <td>Quantity Per Unit</td>
        <td>Unit Price</td>
        <td>Units In Stock</td>
        <td>Units On Order</td>
        <td>Reorder Level</td>
    </tr>
    <asp:Repeater ID="rpProducts" runat="server">
        <ItemTemplate>
            <tr class="item">
                <td><%# Eval("ProductID") %></td>
                <td><%# Eval("ProductName") %></td>
                <td><%# Eval("CompanyName") %></td>
                <td><%# Eval("CategoryName") %></td>
                <td><%# Eval("QuantityPerUnit")%></td>
                <td><%# Eval("UnitPrice")%></td>
                <td><%# Eval("UnitsInStock")%></td>
                <td><%# Eval("UnitsOnOrder")%></td>
                <td><%# Eval("ReorderLevel")%></td>
            </tr>
        </ItemTemplate>
    </asp:Repeater>
</table>

Veriler ASP.NET Repeater kontrolü ile bir tablo yapısında sayfada listelenmektedir. Listelenen verilerin üzerinde bir önceki ve bir sonraki sayfalara geçmek için kullanılacak iki adet ASP.NET LinkButton kontrolü bulunmaktadır. Son olarak sayfalama işleminde parametre olarak sayfada listelenecek veri sayısını ve görüntülenmekte olan sayfa numarasını tutacak iki adet ASP.NET HiddenField kontrolü yer almaktadır.

Bu aşamdan sonra yapılması gereken ASP.NET HiddenField kontrollerinde tutulan parametreleri ASP.NET LinkButton kontrolleri vasıtası ile yönetmek ve gerekli durumlarda veritabanında yer alan ilgili Stored Procedure çağrısı yaparak verileri listelemektir.

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        //Verileri listele
        DataBind();
    }
}

protected void btNext_Click(object sender, EventArgs e)
{
    //Sayfa numarasını bir arttır
    int pageNumber = Convert.ToInt32(hfPageNumber.Value);
    hfPageNumber.Value = (pageNumber + 1).ToString();
    //Verileri listele
    DataBind();
}
protected void btPrevious_Click(object sender, EventArgs e)
{
    //Sayfa numarasını bir azalt
    int pageNumber = Convert.ToInt32(hfPageNumber.Value);
    hfPageNumber.Value = (pageNumber - 1).ToString();
    //Verileri listele
    DataBind();
}
private void DataBind()
{
    //Sayfada listelenecek veri sayısının elde edilmesi
    int pageSize = Convert.ToInt32(hfPageSize.Value);
    //Görüntülenecek sayfa numarasının elde edilmesi
    int pageNumber = Convert.ToInt32(hfPageNumber.Value);

    //İlgili sayfa için verilerin elde edilmesi
    List list = DB.GetInstance().SelectProducts(pageSize, pageNumber);
    //Sayfada listelenecek veri sayısından fazla (+1) veri var mı?
    if (list.Count &gt; pageSize)
    {
        rpProducts.DataSource = list.Take(pageSize);
        btNext.Visible = true; //Sonraki sayfa var
    }
    else
    {
        rpProducts.DataSource = list;
        btNext.Visible = false; //Sonraki sayfa yok
    }
    rpProducts.DataBind();

    //Sayfa numarası 1'den büyük ise önceki sayfa var aksi halde yok
    btPrevious.Visible = (pageNumber &gt; 1) ? true:false;
}

İlk Sayfa

5. Sayfa

Son Sayfa

Reklamlar

2 Responses to SQL ROW_NUMBER() Fonksiyonu ile Sayfalama

  1. abdullah says:

    merhaba bu kodlarda hata alıyorum List list = DB.GetInstance()

    • bulusa says:

      DB.GetInstance() ifadesi benim yazıp uygulamalarımda kullandığım, veritabanı bağlantısı için gerekli olan nesneyi oluşturup dönen DB adında bir sınıf içindeki GetInstance metodunun çağrılmasıdır. Sistem kütüphanesinde olmadığından doğrudan kullanamazsınız. Aşağıdaki gibi bir örnek düşünebilirsiniz. Burada SelectProducts metodu hangi veritabanı kullanıyorsanız ona göre uygun bir şekilde dbo.SelectProducts SP çağırmalıdır.

      public class DB
      {
      private DB() {}
      private static DB instance;
      public static DB GetIntance()
      {
      if(instance == null)
      instance = new DB();
      return instance;
      }

      public List SelectProducts(int pageSize, int pageNumber)
      {
      ….
      }
      }

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Google fotoğrafı

Google hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s

%d blogcu bunu beğendi: