Makale Özeti

ASP.NET ile veritabanı işlemlerini ADO.NETi kullanıyorsunuz uygulamanızın durumuna göre verilerinizi sunmanız gerekebilir (ki genelde gerekir:) ). Verilerin sunulması aşamasında bazı istekleriniz olabilir örneğin verilerin sayfalar halinde sunulması gerekebilir. Bunun için ne yapıyoruz?

Makale

ASP.NET ile SQL Server Üzerinde Sayfalama

ASP.NET ile veritabanı işlemlerini ADO.NETi kullanıyorsunuz uygulamanızın durumuna göre verilerinizi sunmanız gerekebilir (ki genelde gerekir:) ).

Verilerin sunulması aşamasında bazı istekleriniz olabilir örneğin verilerin sayfalar halinde sunulması gerekebilir. Bunun için ne yapıyoruz?

DataGrid web kontrolünün tümleşik sayfalama özelliğini kullanıyoruz. Ve DataGrid kontrolünün PageIndexChanged olayı gerçekleştiğinde hangi (kaçıncı - e.NewPageIndex -) sayfanının görüntüleneceğini belirleyip veritabanından tüm verilerimiz tekar çekiyoruz. Buradaki mekanizma tablodan tüm kayıtları çeker (örneğin bir datasete) ve bu kayıtları asp.net katmanında filtreleyip istenen sayfayı gösterir. Çok sayıda kayıt olan birt tablonuzdaki verileri 10ar 10ar sayfalayarak sunduğunuzu düşünürseniz. Aktif olan sayfa her değiştiğinde tüm tablonuz asp.net tarafına (örneğin datasete) çekilecek ve daha sonra istenilen bölüm sayfalama ayarlarınıza göre seçilip görüntülenecektir.

Bu durum performans açısından kötü sonuçlar doğurabilir. Nasıl bir çözüm bulmalı?

Sql server sunucusu üzerinden sadece istenilen sayfanın verilerini çekersek ve gelen tüm kayıtları listelersek sorun olmaz herhalde? Bunu nasıl yaparız?
Bir Stored Procedure işimizi görecektir.

Yukarıdaki şemada gözüken tablo üzerinde çalışacağız.

CREATE TABLE [tblKisiler] (
[kisiid] [int] IDENTITY (1, 1) NOT NULL ,
[isim] [varchar] (50) COLLATE Turkish_CI_AS NULL ,
[email] [varchar] (100) COLLATE Turkish_CI_AS NULL ,
[adres] [varchar] (250) COLLATE Turkish_CI_AS NULL CONSTRAINT [DF_tblKisiler_adres] DEFAULT (adres),
CONSTRAINT [PK_tblKisiler] PRIMARY KEY CLUSTERED
([kisiid]) ON [PRIMARY]
) ON [PRIMARY]
GO

Şemadaki tabloyu oluşturmak için yukarıdaki t-sql sorgusunu kullanabilirsiniz.

Uygulama için gerekli olan örnek tablomuzu oluşturduktan sonra sayfalanmış veri alabilmemiz için gerekli olan stored proceduree bakalım.

CREATE PROCEDURE Get_tblKisiler (
@PageNumber int,
@PageSize int
)

AS
DECLARE @Start int, @End int
BEGIN TRANSACTION TrsGetPage

SET @Start = ( ( (@PageNumber - 1) * @PageSize) + 1)
IF @@ERROR <> 0
GOTO EyvahHataVar
--baslangic bulundu
SET @End = (@Start + @PageSize - 1)
IF @@ERROR <> 0
GOTO EyvahHataVar
--bitis bulundu

CREATE TABLE #TempKisiler (
OtoID int IDENTITY(1,1) PRIMARY KEY,
kisiid int, isim varchar(50), email varchar(100), adres varchar(250)
)
IF @@ERROR <> 0
GOTO EyvahHataVar
--gecici bir tablo olusturuldu
--OtoID diye yeni bir alan olusturduk tum kayitlara ard arda sayi verdik
-- bu sayede ilgili bolumu (sayfa) secebilecegiz

INSERT INTO #TempKisiler
SELECT kisiid, isim, email, adres FROM [tblKisiler]
IF @@ERROR <> 0
GOTO EyvahHataVar
--tblKisiler tablosundaki kayitlari gecici tabloya yukledik

SELECT kisiid, isim, email, adres
FROM #TempKisiler
WHERE (OtoID >= @Start) AND (OtoID <= @End)
IF @@ERROR <> 0
GOTO EyvahHataVar
--OtoID alaninin sayesinde istedigimiz kayitlari seciyoruz

DROP TABLE #TempKisiler
--gecici tabloyu sildik

COMMIT TRANSACTION TrsGetPage
--transaction onaylandi
RETURN 0

EyvahHataVar:
ROLLBACK TRANSACTION TrsGetPage
--hata olursa rollback yapalim:)
RETURN @@ERROR
GO

Get_tblKisiler stored procedureü @PageNumber ve @PageSize isminde iki parametre alıyor. Bunlar kaçıcı sayfanın  alınacağı ve bir sayfanın kaç kayıt içereceğini belirleyen parametreler. SPmiz gelen parametrelere göre @Start ve @End değişkenlerinin değerlerini hesaplıyor
#TempKisiler adında geçici bir tablo oluşturuyoruz. Asıl tablomuzdan farklı olarak yeni bir alan ekliyoruz OtoID bu alan her kayıt için birbirini takip eden tam sayı alanları oluşmasını sağlıyor. Bu alan sayesinde geçici tablodan WHERE (OtoID >= @Start) AND (OtoID <= @End) şeklinde kayıtları ilgili sayfa değerlerini göz önünde bulundurarak seçiyoruz. Stored Procedure de diğer adımlarda neler yapıldığını yorum satırları yardımıyla inceleyerek anlayabilirsiniz.

tblKisiler tablosuna örnek kayıtlar ekleyerek test edebileceğiniz gibi indireceğiniz zip dosyasındaki veritabanını attach ederek deneyebilirsiniz.

Şimd VS.NET ile yeni bir web application oluşturun ve tblKisiler tablosu için bir mapper sınıf oluşturalım. kisi sınıfının kodu aşağıdadır.

kisi.vb
Imports System.Data.SqlClient

Public Class kisi

    Private _kisiid As Integer

    Private _isim As String

    Private _email As String

    Public Property kisiid() As Integer

        Get

            Return _kisiid

        End Get

        Set(ByVal Value As Integer)

            _kisiid = Value

        End Set

    End Property

    Public Property isim() As String

        Get

            Return _isim

        End Get

        Set(ByVal Value As String)

            _isim = Value

        End Set

    End Property

    Public Property email() As String

        Get

            Return _email

        End Get

        Set(ByVal Value As String)

            _email = Value

        End Set

    End Property

 

    Sub New()

    End Sub

    Sub New(ByVal kisiid As Integer, ByVal isim As String, ByVal email As String)

        Me._kisiid = kisiid

        Me._isim = isim

        Me._email = email

    End Sub

    Public Shared Function GetKisilerPage(ByVal PageNumber As Integer, ByVal PageSize As Integer) As ArrayList

        shared bir function

        Dim con As New SqlConnection("server=(local);database=deneme3;user id=sa;pwd=")

        web.config den veya başka bir kaynakdan connectionstring okundu varsayalım :)

        Dim cmd As New SqlCommand

        cmd.CommandType = CommandType.StoredProcedure

        cmd.CommandText = "Get_tblKisiler"

        cmd.Connection = con

        cmd.Parameters.Add("@PageNumber", PageNumber)

        cmd.Parameters.Add("@PageSize", PageSize)

        Dim rdr As SqlDataReader

        con.Open()

        rdr = cmd.ExecuteReader

        Dim liste As New ArrayList

        Do While rdr.Read

            liste.Add(New kisi(rdr(0), rdr(1), rdr(2)))

        Loop

        rdr.Close()

        con.Close()

        Return liste

    End Function

 

    Public Shared Function GetAllKisiler() As ArrayList

        shared bir function

        Dim sql As String

        sql = "SELECT kisiid,isim,email FROM tblKisiler"

        Dim con As New SqlConnection("server=(local);database=deneme3;user id=sa;pwd=")

        web.config den veya başka bir kaynakdan connectionstring okundu varsayalım :)

        Dim cmd As New SqlCommand(sql, con)

        Dim rdr As SqlDataReader

        con.Open()

        rdr = cmd.ExecuteReader

        Dim liste As New ArrayList

        Do While rdr.Read

            liste.Add(New kisi(rdr(0), rdr(1), rdr(2)))

        Loop

        rdr.Close()

        con.Close()

        Return liste

    End Function

 

End Class

 

Yukarıda görünen kisi sınıfı GetAllKisiler fonksiyonu tablomuzdaki tüm kayıtları seçiyor ve her satırı temsilen kisi sınıfından türemiş bir nesne oluşturup oluşturulan ArrayList türündeki liste nesnesine ekliyor. DataGrid web kontrolünün DataSourceuna  bir arraylist bağlarsanız DataGrid onu reflection ile çözüp görüntüleyecektir.

GetKisilerPage fonksiyonu ise aldığı iki parametreyi SP mize gönderiyor ve spden dönen filtrelenmiş tablonun her satırı için bir kisi nesnesi oluşturup arrayliste ekliyor ve geriye dönüyor.

GetKisilerPage(ByVal PageNumber As Integer, ByVal PageSize As Integer)

Şimdi bu kisi sınıfımız test etmek için bir .aspx sayfası oluşturalım.

<P>Sayfa No:
<asp:textbox id="txtPageNumber" runat="server" Width="32px">2</asp:textbox>
<asp:comparevalidator id="cvPageNumber" runat="server" 
ErrorMessage="sayfa numarası rakam olmalı" Display="Dynamic"
ControlToValidate="txtPageNumber" Type="Integer" Operator="DataTypeCheck">
</asp:comparevalidator></P>
<P>Boyutu :
<asp:TextBox id="txtPageSize" runat="server" Width="32px">3</asp:TextBox>
<asp:CompareValidator id="cvPageSize" runat="server"
ErrorMessage="sayfa boyutu rakam olmalı" ControlToValidate="txtPageSize"
Type="Integer" Operator="DataTypeCheck"></asp:CompareValidator></P>
<P><asp:Button id="btnListele" runat="server" Text="Listele"></asp:Button></P>
<P>&nbsp;</P>
<asp:datagrid id="DataGrid1" runat="server"></asp:datagrid><BR>

Yukarıdaki .aspx sayfası aşağıdaki çıktıyı sağlar. TextBoxlara sadece integer (tam sayı) girilebilmesini sağlamak için CompareValidator geçerlilik kontrollerini içerir.

    Private Sub btnListele_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnListele.Click
        If Page.IsValid Then
            Me.DataGrid1.DataSource = kisi.GetKisilerPage(Me.txtPageNumber.Text, Me.txtPageSize.Text)
            Me.DataGrid1.DataBind()
        End If
    End Sub

ASP.NET Web Formu ile yukarıdaki anlatıldığı gibi stored procedureü, kisi sınıfını test edebilirsiniz. Hangi sayfanın görüntüleneceğini dropdownlist gibi bir yöntem ile sağlayabilirsiniz. Bunun için tablodaki toplam kayıt sayısınıda hesaplatmanız gerekir. Bu işlem için kisi sınıfına shared olan bir fonksiyon veya property ekleyerek tablodaki kayıt sayısını öğrenebilirsiniz.

Bu stored procedure ve sınıf mekanizmaları gerçek yaşamda oluşturacağınız türden uygulamalardır.

Umarım birilerine faydası dokunacak bir makale olmuştur.

İlgili zip dosyasını http://www.cengizhan.com/ASP.NET.SQLServer.Paging.zip adresinden indirebilirsiniz.

Cengiz HAN
cengiz@cengizhan.com