Asp.NET Custom Paging

Bu yazımda sizlere Custom Paging (Özelleştirilmiş Sayfalama) yapmayı anlatacağım. Sanırım DataList'in kendi özelliği olan sayfalama yöntemini kullanmayı çoğunuz biliyorsunuz. Bu yöntem gayet kolay bir yöntem fakat olaya performans açısından bakacak olursak kullanılmaması gereken bir yöntemdir. Veritabanınızdaki ürünler tabonuzda binlerce kayıt olduğunu düşünün, DataList'in allow page özelliğini kullanarak sayfalama yaptığınızda, siz kullanıcıya 10 kayıt gösterecek olsanız dahi datalist veritabanındaki bütün kayıtları çeker ve bu işlem bittikten sonra o seçilen 10 kaydı kullanıcıya gösterir. Bu performans açısından çok kötü olacaktır. Bizim kullanacağımız yöntemde ise bir stored procedure yardımıyla her seferinde sadece istenilen kadar kayıt veritabanından çekilip kullanıcıya gösterilecektir. StoredProcedure yazılırkende geçici tablo oluşturup verileri orda saklayıp sonra sayfalama işlemi yaptırılabiliyordu fakat MsSQL 2005 ile birlikte gelen Row_Number() özelliği çok daha performanslı bir şekilde çalışıyor. Bu örnekte de Repeater'ile Düzenleme,Güncelleme ve Silme işlemlerini anlattığım yazımda kullandığım ornek isimli veritabanını ve blog isimli tabloyu kullanacağım. Önce saklı yordamımızı oluşturalım bunun için veritabanına sağ tıklayıp New Query diyebilirsiniz yada veritabanını genişletip Programmability'den Stored Procedures'ı bulup ona sağ tıklayıp New Stored Procedure diyebilirsiniz.

CREATE PROCEDURE SP_BLOG
@KayitSayi int,
@SayfaNum int
AS
SET NOCOUNT ON;
DECLARE @BaslangicID int,@BitisID int
SET @BaslangicID=((@SayfaNum -1)*@KayitSayi)+1
SET @BitisID=(@BaslangicID+@KayitSayi)-1

;WITH NumberedRows AS 
(SELECT * ,Row_Number() OVER (ORDER BY id desc) AS RowNumber FROM blog) 

SELECT * FROM NumberedRows 
where RowNumber between @BaslangicID and @BitisID order by id desc

Kodları yazdıktan sonra execute ederseniz Stored Procedure oluşturma işlemini tamamlamış olursunuz. Yaptığı işi anlatmak gerekirse gönderilen sayfa numarası ve kayıt sayısı değişkenlerine göre başlangıç ve bitiş id'lerini hesaplıyor. Blog tablosundaki verileri NumberedRows isimli geçici bir tablo oluşturarak sıralı bir şekilde oraya dolduruyor ve önceden hesapladığı Başlangıç-Bitiş id değerlerine göre seçilen kadar kaydı sizlerin huzuruna sunuyor (: MsSQL ile işimiz bittiğine göre Asp.NET kısmına geçebiliriz. Ben repeater kullanarak anlatacağım ama sizler DataList yada GridView da kullanabilirsiniz. Oluşturduğum sayfaya 1 adet Repeater ve 1 Adet PlaceHolder ekliyorum default.aspx kodlarım şu şekilde ;

<asp:repeater ID="Repeater1" runat="server">
<ItemTemplate>
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td><%# Eval("baslik") %></td>
</tr>
<tr>
<td> <%# Eval("icerik") %></td>
</tr>
</table>
</ItemTemplate>
</asp:repeater>

<asp:PlaceHolder ID="plhLinkler" runat="server"></asp:PlaceHolder>

Sayfaya ekleyeceklerimiz bittiğine göre CodeBehind kısmına geçebiliriz.

Default.aspx.cs

    public partial class _Default : Page
    {
        public SqlConnection baglanti;
        public int kayitSayi;
        public _Default()
        {
            baglanti = new SqlConnection("Data Source=.;Initial Catalog=ornek;User Id=sa;Password=sifreniz;");
            kayitSayi = 10;//sayfada gösterilecek kayıt sayısı
        }

        protected void Page_Load(object sender, EventArgs e)
        {            
            string sayfa = Request.QueryString["Sayfa"];
            if (String.IsNullOrEmpty(sayfa))
                doldur(1, kayitSayi);
            else 
                doldur(Convert.ToInt32(sayfa), kayitSayi);           
        }

        public void doldur(int sayfaNo, int kayitSayi)
        {
            baglanti.Open();
            SqlCommand cmd = new SqlCommand();
            //Komut tipini StoredProcedure olarak belirledik.
            cmd.CommandType = CommandType.StoredProcedure;
            //Kullanacağımız bağlantıyı seçtik.
            cmd.Connection = baglanti;
            //Kullanacağımız StoredProcedure'ın adını yazdık.
            cmd.CommandText = "SP_BLOG";
            //Procedure'ın alacağı parametreleri belirledik.
            cmd.Parameters.AddWithValue("@KayitSayi", kayitSayi);
            cmd.Parameters.AddWithValue("@SayfaNum", sayfaNo);

            //Verileri DataTable nesnesine dolduduk..
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            DataTable dt = new DataTable();
            da.Fill(dt);

            //Repeater'a veri kaynağı olarak oluşturduğumuz DataTable nesnesini seçtik.
            Repeater1.DataSource = dt;
            Repeater1.DataBind();
            baglanti.Close();

            //Ekrana linkleri yazdıracak olan metodumuzu çağıtdık.
            linkOlustur(sayfaNo, sayfaSayisi());
        }

        //Toplam sayfa sayısını hesaplayan metot
        public int sayfaSayisi()
        {
            SqlCommand cmd = new SqlCommand("Select Count(id) from blog",baglanti);
            int sayfaSayi = Convert.ToInt32(cmd.ExecuteScalar());
            cmd.Dispose();
            int pc;
            if (sayfaSayi % kayitSayi == 0)
                pc = sayfaSayi / kayitSayi;
            else
                pc = (sayfaSayi / kayitSayi) + 1;
            return pc;
        }

        //Ekrana linkleri oluşturan metot
        public void linkOlustur(int GecerliSayfa, int toplamSayfaSayisi)
        {
            Literal lt1 = new Literal();
            if (!((GecerliSayfa - 1) < 1))
            {
                lt1.Text = "<li><a href='?Sayfa=1' title='İlk Sayfa'>««</a></li>";
                lt1.Text += "<li><a href='?Sayfa=" + (GecerliSayfa - 1) + "' title='Önceki Sayfa'>«</a></li>";
                plhLinkler.Controls.Add(lt1);
            }
            lt1.Controls.Clear();
            lt1.Dispose();

            if ((GecerliSayfa + 5) < 19)
            {
                int orta = 19;
                for (int i = 1; i <= orta; i++)
                {
                    if (i > toplamSayfaSayisi)
                        continue;
                    Literal ltl = new Literal();
                    if (i == GecerliSayfa)
                    {
                        Literal lbl = new Literal();
                        lbl.Text = "<li><a href='#' class='current'>" + i.ToString() + "</a></li>";
                        //lbl.CssClass = "current";
                        plhLinkler.Controls.Add(lbl);
                    }
                    else
                    {
                        ltl.Text = "<li><a href='?Sayfa=" + i + "' title='" + i.ToString() + ". Sayfa'>" + i.ToString() + "</a></li>";
                        plhLinkler.Controls.Add(ltl);
                    }

                    ltl.Controls.Clear();
                    ltl.Dispose();
                }
            }
            else
            {
                int orta = GecerliSayfa - 4;
                int son = GecerliSayfa + 12;
                for (int i = orta; i <= son; i++)
                {
                    if (son > toplamSayfaSayisi)
                        son = toplamSayfaSayisi;
                    Literal ltl = new Literal();
                    if (i == GecerliSayfa)
                    {
                        Literal lbl = new Literal();
                        lbl.Text = "<li><a href='#' class='current'>" + i.ToString() + "</a></li>";
                        //lbl.CssClass = "current";
                        plhLinkler.Controls.Add(lbl);
                    }
                    else
                    {
                        ltl.Text = "<li><a href='?Sayfa=" + i + "' title='" + i.ToString() + ". Sayfa'>" + i.ToString() + "</a></li>";
                        plhLinkler.Controls.Add(ltl);
                    }
                    ltl.Controls.Clear();
                    ltl.Dispose();
                }
            }

            Literal lt2 = new Literal();
            if (!((GecerliSayfa + 1) > toplamSayfaSayisi))
            {
                lt2.Text = "<li><a href='?Sayfa=" + (GecerliSayfa + 1) + "' title='Sonraki Sayfa'>»</a></li>";
                lt2.Text += "<li><a href='?Sayfa=" + toplamSayfaSayisi + "' title='Son Sayfa'>»»</a></li>";
                plhLinkler.Controls.Add(lt2);
            }
            lt2.Controls.Clear();
            lt2.Dispose();
        }

    }

Yapılanları özetleyecek olursam ki olsam iyi olacak gibi (: Tıklanan sayfa numarasını almak için, Sayfa isimli bir QueryString tanımlayıp aynı isimde bir stringe eşitledim ve bu querystring boş mu, dolu mu diye kontrol ettim. Boşsa doldur isimli metoduma, sayfa numarasını 1 olarak gönderdim, doluysa sayfa numarası olarak querystring'ten gelen yani kullanıcının tıkladığı sayfa numarasını doldur isimli metoduma gönderdim. Doldur isimli metotumda cmd isimli bir SqlCommand nesnesi oluşturdum. Oluşturduğumuz SqlCommand'ın komut tipini storedprocedure yapıp, komut adına ise önceden oluşturduğumuz storedprocedure'ın adını yani SP_BLOG adını verip, sayfaNo ve kayitSayi değerlerini, StoredProcedure'a parametre olarak gönderdik. SqlDataAdapter ve DataTable aracılığı ile Repeater'a verileri doldurduktan sonra sayfa linklerini oluşturacak olan metodumuzu çağırdık. Yazdığım bu metot tüm sayfa numaralarını peşpeşe sıralamaz size şöyle bir görünüm sunar;

Sayfala

Tabi kendi tasarımınıza still dosyalarınıza göre gerekli değişiklikleri yapmanız gerekmekte(: Elimden geldiğince anlatmaya çalıştım, umarım faydalı olmuştur. Her türlü soru veya düşüncenizi yorum kısmından ulaştırabilirsiniz. Hepinize kolay gelsin.

Sosyal Ağlarda Paylaşın

Share on Tumblr

Facebook Yorumları


Yorumlar (4)

  • bilal niişanci Yanıtla

    eline sağlik güzel anlatmişsin anlatiklarindan çök faydalandim

    2/15/2012 20:01:20
  • bilal nişanci Yanıtla

    bir sorum olacak ben bu anlatilanlari yaptim çalişiyor fakat sayfalamada stili nasil verebiliriz epey uğraşmama rahmen yapamadim acaba stil kodlarini verebilirmisin

    2/15/2012 23:10:03
  • B-Rk Yanıtla

    Seçili olanın style ı bu şekilde ama çok detaylı stillendirme yapman gerekebilir o yüzden yazmakla olmaz gibi, ul li a falan hepsine ayrı ayrı stil verebilirsin kafana göre, nasıl bir görünüm istiyorsan (: .current{ background: #666; border:1px solid #222; color:#fff; }

    2/29/2012 09:32:39
  • Hakan Yanıtla

    Emeğinize sağlık... Yabancı kaynaklarda bile çok araştırdığım nadide ve önemli bilgilerden birisi...

    6/3/2012 01:45:54

Yorum Yapın