ASP.NET 2.0’da Çok Katmanlı Uygulama Yapıları

ASP.NET 2.0’da Çok Katmanlı Uygulama Yapıları


Bu makale, ASP.NET 2.0 ile orta seviye ve(ya) ileri uygulamalar geliştirenler içindir.
Aşağıdaki kodları www.kitaplar.net sitesinden indirebilirsiniz. 
Makalede çok katmanlı uygulama yapısı örnek bir uygulama üzerinde anlatılacak.
Öncelikle şu soruyu sorarak başlayalım; çok katmanlı uygulama yapısı ne demektir?
Bu ifade basitçe uygulamamızı katmanlara bölmek anlamına gelir.
Peki, katmanlara bölmek ne demek?
Katmanlara bölmek demek, uygulamamızı kendi içinde bir bütün oluşturan ve diğer katmanlarla ilişkiye geçen bağımsız bölümlerden oluşturmak demektir.
Bunun en güzel örneği “3-tier” denilen üç katmanlı modeldir.

Bu modelde, uygulamanın veritabanı ile ilişkide olan kısmı ayrı bir katman, bu kısmı sorgulayıp verileri elde eden kısmı ayrı bir katman ve en sonunda sunumu yapan kısmı ayrı bir katmandır. Verilerin saklandığı veritabanını da işin içine katarsak aslında uygulamamız bütününde dört katmanlı olmuş oluyor.
Günümüzün modern yazılım mimarisinde çok katmanlı modeller oldukça yaygın kullanılmaktadır.
Geleneksel mimariye göre daha esnek bir yapı sağlayan bu model, daha modüler daha taşınabilirdir.
Bu mimari sayesinde ekip çalışması oluşturmak daha kolaydır.
Ancak dezavantajı kompakt yapıya göre daha dolaylı olmasıdır (zor değil, dolaylı)
Bütünleşik yapıda bütün kodlar elinizin altında bir yerdedir.
Çok katmanlı yapıyı oluşturmak, anlatmaktan daha kolaydır.
Ben de konunun daha iyi anlaşılması için bu mimari ile bir uygulama geliştireceğim ve anlatımlarımı bunun üzerinden yapacağım.

Çok Katmanlı Bir Uygulama
Uygulamamız hepimizin bildiği northwind verilerini kullanacak ve SQL server 2005 Express veritabanını ile iletişim sağlayacak.
Bu yapıda temel üç tane dosya oluşturacağım. Bu dosyalardan ikisi birer class (sınıf) dosyası bir tanesi de kullanıcı arabirimini oluşturan bir .aspx web sayfası olacak.

Yapı aşağıdaki gibi olacak:



 Burada BOL ifadesi “Business Object Layer” yani iş yapan kodların oluşturduğu katmanı temsil etmektedir.

BOL_sinifi.vb dosyasında, veritabanından sorgulamayı yapacak kodlar bulunmaktadır.
Ancak bu sorgulamayı doğrudan değil Veritabani_Sorgu.vb dosyasındaki kodlar vasıtası ile yapacak.
Başka bir ifade ile uygulamanın kodları veritabanı sorgusu yapan kodlarla ayrılmış oluyor.
Veritabanı ile doğrudan iletişime geçen kodlar Veritabani_Sorgu.vb içindeki kodlar olacak.

Buraya kadar biraz karışık gibi ama kodlarımızı görünce biraz daha netleşecek.
Öncelikli olarak uygulamamızın ne yapacağını bir görelim.
Uygulama “northwind” veritabanından “Custormers” tablosundan veriler getirecek, güncelleyecek, ekleyecek ve silecek.


 
Öncelikli olarak veritabanı ile ilişkilerimizi düzenleyecek Veritabani_Sorgu.vb dosyamızı oluşturalım.

Veritabani_Sorgu.vb

Imports Microsoft.VisualBasic
Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration

Public Class Veritabani_Sorgu

    Private Shared veritabani_baglanti As String

    Shared Sub New()
        veritabani_baglanti = ConfigurationManager.ConnectionStrings("connectionstring").ConnectionString
    End Sub

    Public Shared Function ExecuteNonQuery(ByVal sql As String, ByVal parametreler() As SqlParameter) As Integer
        Dim baglanti As New SqlConnection(veritabani_baglanti)
        Dim komut As New SqlCommand(sql, baglanti)
        For i As Integer = 0 To parametreler.Length - 1
            komut.Parameters.Add(parametreler(i))
        Next
        baglanti.Open()
        Dim donus_degeri As Integer = komut.ExecuteNonQuery()
        baglanti.Close()
        Return donus_degeri
    End Function

    Public Shared Function ExecuteDataSet(ByVal sql As String) As DataSet
        Dim ds As New DataSet
        Dim da As New SqlDataAdapter(sql, veritabani_baglanti)
        da.Fill(ds)
        Return ds
    End Function

    Public Shared Function ExecuteScalar(ByVal sql As String, ByVal parametreler() As SqlParameter) As Object
        Dim baglanti As New SqlConnection(veritabani_baglanti)
        Dim komut As New SqlCommand(sql, baglanti)
        For i As Integer = 0 To parametreler.Length - 1
            komut.Parameters.Add(parametreler(i))
        Next
        baglanti.Open()
        Dim donus_degeri As Object = komut.ExecuteScalar
        baglanti.Close()
        Return donus_degeri
    End Function

    Public Shared Function ExecuteDataSet(ByVal sql As String, ByVal parametreler() As SqlParameter) As DataSet
        Dim ds As New DataSet
        Dim da As New SqlDataAdapter(sql, veritabani_baglanti)
        For i As Integer = 0 To parametreler.Length - 1
            da.SelectCommand.Parameters.Add(parametreler(i))
        Next
        da.Fill(ds)
        Return ds
    End Function


End Class




Veritabani_Sorgu class’ının kodlarına baktığımızda veritabanı ile bağlantıya geçip jenerik sorgulamalar yapan bir yapıya sahip.

Öncelikli olarak,

  veritabani_baglanti = ConfigurationManager.ConnectionStrings("connectionstring").ConnectionString

Satırı  ile web.config dosyamızdan bağlantı ifademizi alıyor.

Bu string şöyle:

<connectionStrings>
    <add name="connectionstring" connectionString="data source=.\sqlexpress;initial catalog=NORTHWIND;User ID=sa;Password=sa" providerName="System.Data.SqlClient"/>
  </connectionStrings>



(Değerleri kendinize göre uyarlamayı unutmayın.)
Devamında ExecuteNonQuery, ExecuteDataSet, ExecuteScalar, gibi fonksiyonlar tanımlanmış. Bu fonksiyonlar jenerik olup gelen her parametre değerine göre veritabanı ile işlem yapıp değer döndürürler. 
Örneğin ExecuteNonQuery fonksiyonu gönderilen parametrelere göre veritabanına bir şeyler ekler, siler veya günceller.

ExecuteDataSet  Gönderilen parametre değerlerine göre alıcıya bir dataset döndürür. Burada bu ifadeler tamamıyla genel ve herhangi bir başka katmanın  bir parçası  değil ama diğer katmanlara servis yapan bir yapıdır.
Başka katmandan gelen parametreleri alıp veritabanından gerekli işlemleri yapıp değer döndürmektedirler. İşin özü burada. Uygulamalarımızda böyle genel katman(lar) oluşturmalıyız.  En azından veritabanı ile ilişkiler için. Böylece her kod(iş) katmanından buraya  kolayca sorgulama oluşturabilir, bu yapıyı zenginleştirebiliriz.

Bu katmanı kullanacak iş yapan (business) katman daha özel verilerle ilgilenmekte ve veritabanı işlemlerini buraya yaptırmaktadır.
Şimdi “iş yapan” (business) kod katmanımıza gelirsek:
Onun kodları da şöyle:


BOL_sinifi.vb

Imports System.Data
Imports System.Data.SqlClient
Imports System.Collections.Generic

Public Class BOL_sinifi
    Private strID As String
    Private strSirket As String
    Private strIletisim As String
    Private strSehir As String

    Public Property MusteriID() As String
        Get
            Return strID
        End Get
        Set(ByVal value As String)
            strID = value
        End Set
    End Property

    Public Property SirketIsmi() As String
        Get
            Return strSirket
        End Get
        Set(ByVal value As String)
            strSirket = value
        End Set
    End Property

    Public Property IletisimIsmi() As String
        Get
            Return strIletisim
        End Get
        Set(ByVal value As String)
            strIletisim = value
        End Set
    End Property

    Public Property Sehir() As String
        Get
            Return strSehir
        End Get
        Set(ByVal value As String)
            strSehir = value
        End Set
    End Property

    Public Shared Function Insert(ByVal bol_sinifi As BOL_sinifi) As Integer
        Dim sql As String
        sql = "insert into customers(customerid,companyname,contactname,country) values(@custid,@company,@contact,@country)"
        Dim parametreler(3) As SqlParameter
        parametreler(0) = New SqlParameter("@custid", bol_sinifi.MusteriID)
        parametreler(1) = New SqlParameter("@company", bol_sinifi.SirketIsmi)
        parametreler(2) = New SqlParameter("@contact", bol_sinifi.IletisimIsmi)
        parametreler(3) = New SqlParameter("@country", bol_sinifi.Sehir)
        Return Veritabani_Sorgu.ExecuteNonQuery(sql, parametreler)
    End Function

    Public Shared Function Update(ByVal bol_sinifi As BOL_sinifi) As Integer
        Dim sql As String
        sql = "update customers set companyname=@company,contactname=@contact,country=@country where customerid=@custid"
        Dim parametreler(3) As SqlParameter
        parametreler(0) = New SqlParameter("@company", bol_sinifi.SirketIsmi)
        parametreler(1) = New SqlParameter("@contact", bol_sinifi.IletisimIsmi)
        parametreler(2) = New SqlParameter("@country", bol_sinifi.Sehir)
        parametreler(3) = New SqlParameter("@custid", bol_sinifi.MusteriID)
        Return Veritabani_Sorgu.ExecuteNonQuery(sql, parametreler)
    End Function

    Public Shared Function Delete(ByVal bol_sinifi As BOL_sinifi) As Integer
        Dim sql As String
        sql = "delete from customers where customerid=@custid"
        Dim parametreler(0) As SqlParameter
        parametreler(0) = New SqlParameter("@custid", bol_sinifi.MusteriID)
        Return Veritabani_Sorgu.ExecuteNonQuery(sql, parametreler)
    End Function

    Public Shared Function SelectAll() As List(Of BOL_sinifi)
        Dim ds As DataSet = Veritabani_Sorgu.ExecuteDataSet("select customerid,companyname,contactname,country from customers")
        Dim arr As New List(Of BOL_sinifi)
        For Each row As DataRow In ds.Tables(0).Rows
            Dim bol_sinifi As New BOL_sinifi
            bol_sinifi.MusteriID = row("customerid")
            bol_sinifi.SirketIsmi = row("companyname")
            bol_sinifi.IletisimIsmi = row("contactname")
            bol_sinifi.Sehir = row("country")
            arr.Add(bol_sinifi)
        Next
        Return arr
    End Function

    Public Shared Function SelectSingle(ByVal custid As String) As BOL_sinifi
        Dim params(0) As SqlParameter
        params(0) = New SqlParameter("@custid", custid)
        Dim ds As DataSet = Veritabani_Sorgu.ExecuteDataSet("select customerid,companyname,contactname,country from customers where customerid=@custid", params)
        Dim row As DataRow = ds.Tables(0).Rows(0)
        Dim c As New BOL_sinifi
        c.MusteriID = row("customerid")
        c.SirketIsmi = row("companyname")
        c.IletisimIsmi = row("contactname")
        c.Sehir = row("country")
        Return c
    End Function
End Class


Bu kodlara dikkatli bakacak olursanız fonksiyonlar, SQL ifadeleri, özellikler ve diğerlerini görürsünüz.
Bu katman sunum katmanındaki taleplerin alınıp işlendiği katmandır.
Diğer bir ifade ile aspx sayfasına kodlar doğrudan yazılmayıp bu katman sayesinde işler yapılmaktadır. Bu katman da gelen talepleri biraz önce incelediğimiz jenerik katman sayesinde yerine getirmektedir.
Devamında neler olduğunu gelecek makalemde inceleyeceğiz.