Veritabanı uygulamalarında
çok katlı mimari (N-tier) popüler olmakla beraber hayati bir öneme sahiptir.
Bu mimari türü, bazı temel işlemlerin farklı katmanlar üzerinden yapılmasını
sağlar. Bu modelde veritabanı üzerinde sırasıyla şu katmanlar bulunur:
· En altta veri
erişim katmanı (Data Access Layer);
· Ortada
iş katmanı (Business Layer);
· En üstte
sunum katmanı (Presentation Layer).
Bu katmanlar bağımsız
olmakla birlikte biribirleriyle haberleşebilirler. Uygulama ihtiyaçlarına göre
bu katmanların kendi alt katmanları da olabilir. Veri erişim katmanı tablolar,
stored procedure’lar ve diğer bileşenler ile sağlam bir ilişki kurarak veri
mantığını sağlar. Veritabanına esnek, kolay, hızlı ve güvenli erişim sağlamanın
yanı sıra diğer katmanlardan bağımsız olarak veritabanı yapılarını mantıksal
bir biçimde soyutlar. Örneğin bir tablo satırında yapılan değişiklikler, uygulamanın
diğer kısımlarını etkilemez. Diğer katmanlar isteklerini veri katmanına gönderirler.
Bu istekleri alan veri katmanı, isteğe göre tablolara kayıt ekleme, silme, kayıt
güncelleştirme, stored procedure’lar ile kayıt seçme, dataset geri döndürme
gibi işlemleri yapacaktır. Projelerde böyle bir veri erişim katmanın bulunması,
veritabanı güvenliği açısından performans, hız, güvenlik ve kod okunabirliği
açısından avantajlar sağlar. Örnek olarak, sunum katmanı içindeyken bağlantı
cümlesini, bağlantı nesnesi veya komut nesnesi özelliklerini bilmek gerekmiyor.
İyi hazırlanmış bir veri erişim katmanı, ileride başka projelerde de rahatlıkla
kullanılabilir. Farklı amaçlar için hazırlanmış stored procedure’lar, bazen
bir satırı, bir listeyi veya bir sayıyı geri döndürebilirler. Bunları çalıştırmak
için çeşitli metodlar yazarız. Bu metodlar komut nesnesi oluşturma, varsa parametrelerin
özelliklerini doldurma, çalıştırma ve sonunda bir sonuç veya veri listesi alma
şeklinde olabilir. Mantık genelde az farklılık gösterirse de, çoğu zaman benzer
adımları tekrar ederiz. Bu gereksiz tekraralardan kaçınmak için yazacağımız
sınıf veya sınıflar, bizi benzer kodları defalarca yazmakan kurtarır.
Sınıfımıza ait
metodlar bağlantı açma-kapama, parametre hazırlama, komut nesnesi hazırlama,
stored procedure çalıştırarak bir değer döndürme ve dataset doldurma işlemleridir.
Şimdi kullanacağımız sınıfın kodlarını yazalım.
using
System;
using
System.Windows.Forms;
using
System.Data;
using
System.Data.SqlClient;
//
Veri erişimi için ClassDAL sınıfı
public
class
ClassDAL: IDisposable
{
//
Connection string değişkeni tanımla
private
string m_ConStr;
//
SqlConnection veri kaynağına bağlantı hattını yapacak olan nesne.
private
SqlConnection con = null;
//
Yapıcı metod bir string parametresi alıyor
public
ClassDAL(string sConStr)
{
this.strConnection
= sConStr;
}
//
Sınıfa ait strConnection özelliği ile m_ConStr değişkeni
//
atanıyor ve bağlantı yaratılıyor.
public
string strConnection
{
get
{
return
m_ConStr;
}
set
{
m_ConStr
= value;
try
{
//
SqlConnection bağlantı nesnesi yarat
this.con
= new SqlConnection(value);
}
catch
(Exception ex)
{
//
SqlConnection nesnesi yaratılırken hata oluştu
MessageBox.Show
(ex.Message);
}//end
try-catch
}
}
//
SQL sunucuyla olan bağlantı açılır.
private
void OpenDBConnection()
{
try
{
//
Eğer bağlantı açık değilse
if
(con.State != ConnectionState.Open)
con.Open();
// Bağlantıyı aç
}
catch
(Exception ex)
{
//
Veritabanına bağlanırken hata oluştu.
MessageBox.Show
(ex.Message);
}//end
try-catch
}
//
SQL sunucuyla olan bağlantı kapatılır.
public
void CloseDBConnection()
{
try
{
if
(con != null)
con.Close();
// Bağlantıyı kapat
}
catch
(Exception ex)
{
MessageBox.Show
(ex.Message);
}//end
try-catch
}
//
Kaynakları serbest bırak.
public
void Dispose()
{
//
Bağlantı nesnesinin serbest bırakılması
if
(con != null)
{
con.Dispose();
con
= null;
}//end
if
}
}
|
Şimdi stored procedure
için parametrelerimizi hazırlayacak olan SetParameter metodumuzu ekleyelim.
Uygulama içinden parametrenin adı, tipi, boyu, yönü ve değeri girilir. Çeşitli
değer aktarım tipleri (Input, Output, ReturnValue) bildirebiliriz. İlk önce
SqlParameter nesnesini oluşturalım. Daha sonra, bunun yönünü Direction yoluyla
belirleyelim ve parametrenin değerini verelim.
/*
SetParameter:
Stored procedure için parametre hazırlar. Yönü string bir değerle
verilir.
Daha sonra, alınan bu değer Direction değerlerinden birine çevrilir.
Geriye
bir SqlParameter çevrilir.
*/
//
"sParamName": Parametre adı.
//
"DbType": Parametre tipi.
//
"iSize": Parametre boyu.
//
"sDirection": Parametrenin yönü.
//
"oParamValue": Parametrenin değeri.
public
SqlParameter SetParameter(string sParamName,SqlDbType
DbType, Int32 iSize, string sDirection, object
oParamValue)
{
//
SqlParameter nesnesi tanımla
SqlParameter
param = new SqlParameter(sParamName, DbType,
iSize);
//"sDirection"
den alınan string değer, switch-case komutu
//
ile Parametreye yön özelliği veriliyor.
switch
(sDirection)
{
case
"Input":
param.Direction
= ParameterDirection.Input;
break;
case
"Output":
param.Direction
= ParameterDirection.Output;
break;
case
"ReturnValue":
param.Direction
= ParameterDirection.ReturnValue;
break;
case
"InputOutput":
param.Direction
= ParameterDirection.InputOutput;
break;
default:
break;
}//end
switch
//
Parametere değerini ver
param.Value
= oParamValue;
return
param;
}
|
GetCommand metodumuz
ise stored procedure adı ve varsa parametreler girildiğinde, bize SqlCommand
nesnesi hazırlar.
/*
GetCommand
metodu için bir stored procedure adı ve parametreler
girilir.
Geriye SqlCommand nesnesi döndürür.
*/
//
"sProcName": Çalıştırılacak stored procedure adı.
//
"prms": Parametreler.
public
SqlCommand GetCommand(string sProcName, SqlParameter[]
prms)
{
//
SqlCommand nesnemizi oluşturuyoruz.
SqlCommand cmd = new
SqlCommand(sProcName, con);
//
Stored Procedure çağrısı
cmd.CommandType
= CommandType.StoredProcedure;
// Parameters
koleksiyonuna Add metodu ile ekleme yap.
if
(prms != null)
{
foreach
(SqlParameter parameter in prms)
cmd.Parameters.Add( parameter );
}
//end if
return cmd; // SqlCommand nesnesini döndür.
}
|
ExecSProcRetVal
metodunu ekleyelim. Bu metod bir stored procedure çalıştırır ve geriye bir tamsayı
döndürür. Örneğin bir tablodaki satır sayısını bilmek veya toplam stok değerini
öğrenmek istediğimizde bu metodu kullanabiliriz.
/*
ExecSProcRetVal
metodu bir Stored procedure çalıştırır ve geriye
bir
tamsayı değer döndürür.
*/
//
"sProcName": Stored procedure adı.
//
"prms" Parametreler.
//
"sRetValParam" RETURN ile değer döndüren parametremizin adı.
public
int
ExecSProcRetVal(string sProcName, SqlParameter[]
prms,string sRetValParam)
{
//
SqlCommand nesnesini hazırla.
SqlCommand
cmd = GetCommand(sProcName, prms);
//
Bağlantımızı açıyoruz.
OpenDBConnection();
// Komutumuz
tek bir değer döndüreceğinden ExecuteScalar metodu ile
//
çalıştırıyoruz.
cmd.ExecuteScalar();
// Bağlantımızı
kapatıyoruz.
CloseDBConnection();
// Parametrenin Value özelliği object
tipi olduğu için
//
tamsayı tipine çevrilmesi gerekiyor.
return
Convert.ToInt32(cmd.Parameters[sRetValParam].Value);
}
|
GetDataSet metodumuzla
bir stored procedure çalıştırdıktan sonra, bilgileri bir DataSet veri kümesi
içine alıyoruz. Böylece, bilgiler istemci makine belleğinde tutulabilirler.
Bir windows uygulamasında DataGrid için DataSet nesnesini bağlarken, bu metod
yararlı olabilir.
/*
GetDataSet
metodu stored procedure çalıştırlması sonucunda, dataset
içini
doldurur ve bu nesneyi geriye gönderir.
*/
// "sProcName": Stored procedure adı.
// "prms" Parametreler.
public
DataSet GetDataSet(string sProcName, SqlParameter[]
prms)
{
DataSet
ds = new DataSet(); //
DataSet nesnesini oluştur.
try
{
//
Bağlantımızı açıyoruz.
OpenDBConnection();
//
SqlCommand nesnesini hazırla.
SqlCommand
objCmd = GetCommand(sProcName, prms);
//
SqlDataAdapter nesnesini oluştur.
SqlDataAdapter
myAdptr = new SqlDataAdapter();
//
objCmd nesnesini işaret et.
myAdptr.SelectCommand
= objCmd;
//
myAdptr oluşturduğumuz DataSet nesnesini doldurur.
myAdptr.Fill(
ds, "myTable" );
}
catch
(Exception ex)
{
MessageBox.Show
(ex.Message);
}
finally
{
CloseDBConnection();
// Bağlantımızı kapatıyoruz.
}//end
try-catch-finally
return
ds;
}
|
Veri erişim sınıfımızdan
nasıl yararlanacağımızı gösteren bir örnekle başlayalım:
Öncelikle makalemizde
kullanacağımız stored procedure nesnelerini oluşturalım. Bunlar için Sql Server
içindeki Nortwind veritabanını kullanacağız. Birinci stored procedure usp_GetEmployees,
Employees tablosundan LastName, FirstName ve Title sütunlarını listeliyor.
CREATE
PROCEDURE usp_GetEmployees
AS
SELECT
LastName, FirstName, Title
FROM
Employees
ORDER
BY LastName
GO
|
İkinci stored procedure
usp_CountEmployees ise COUNT() yardımıyla, Employees tablosunun içindeki satır
sayısını veriyor.
CREATE
PROCEDURE
usp_CountEmployees
@count_employees
int OUTPUT
AS
SELECT
@count_employees = COUNT(*) FROM Employees
GO
|
Şimdi VS
.NET içinden yeni bir Windows uygulaması başlatalım. Programımız basit bir şekilde
yukarıdaki stored procedure’lardan herhangi birini çalıştıracak. Formumuza DataGrid,
button ekleyelim. ClassDAL sınıfımızı da uygulamamıza dahil edelim. Ayrıca,
bir ayar dosyası da ekleyelim.
Anahtar adını ve
değerini kendinize göre giriniz. Örneğin bendeki App.config dosyasında:
key="ConnectionString"
value="data
source=localhost;initial catalog=Northwind;Integrated Security=SSPI"
using
System;
using
System.Drawing;
using
System.Collections;
using
System.ComponentModel;
using
System.Windows.Forms;
using
System.Configuration;
using
System.Data;
using
System.Data.SqlClient;
private
string
myConnString;
private
void Form1_Load(object
sender, System.EventArgs e)
{
//
Bağlantı hattı için kurulum bilgilerini ayar dosyasından oku.
myConnString
= ConfigurationSettings.AppSettings["ConnectionString"];
if
((myConnString != null) || (myConnString
!= ""))
{
//
ClassDAL sınıfımızdan myClassDAL nesnesi oluşturuluyor.
ClassDAL
myClassDAL = new ClassDAL(myConnString);
try
{
//
DataSet nesnesini tanımla.
DataSet
myDataSet = new DataSet();
//
ClassDAL sınıfı içinden GetDataSet metodunu çağır.
//
"usp_GetEmployees" prosedüründen gelen sonuçlar dataset
//
içine doldurulur.
myDataSet
= myClassDAL.GetDataSet("usp_GetEmployees", null);
//
dataGrid1’e myDataSet’i bağla.
dataGrid1.SetDataBinding(myDataSet,
"myTable");
}
catch
(Exception ex)
{
MessageBox.Show(ex.ToString());
// Hata mesajı ver.
}
finally
{
myClassDAL.Dispose();
// Sınıfı sonlandır.
}//end
try-catch-finally
}
else
{
MessageBox.Show("Ayar
dosyasından bağlantı cümlesi okunamadı.");
}//end
if
}
|
Şimdi uygulamamızı
çalıştırırsak Employees tablosundaki kayıtların stored procedure yardımıyla
DataGrid içinde listelendiği görülecektir.
Düğmeye basarsak,
Employees tablosundaki kayıtların sayısını alırız.
private
string myConnString;
//
Bağlantı hattı için kurulum bilgilerini ayar dosyasından oku.
//
myConnString = ConfigurationSettings.AppSettings["ConnectionString"];
//
myConnString değeri daha önce atanır.
private
void button1_Click(object
sender, System.EventArgs e)
{
if
((myConnString != null) || (myConnString
!= ""))
{
//
ClassDAL sınıfımızdan myClassDAL nesnesi oluşturuluyor.
ClassDAL
myClassDAL = new ClassDAL(myConnString);
try
{
//
Parametreleri hazırla.
SqlParameter[]
prms ={
myClassDAL.SetParameter("@count_employees",
SqlDbType.Int, 4, "Output", 0)};
//
ClassDAL sınıfı içinden ExecSProcRetVal metodunu çağır.
//
Stored procedure’den programa integer değer döndürüyoruz.
//
Geri dönen değeri işaret eden parametrenin adını veriyoruz.
MessageBox.Show(
"Personel sayısı: " +myClassDAL.ExecSProcRetVal("usp_CountEmployees",
prms, "@count_employees").ToString());
}
catch
(Exception ex)
{
MessageBox.Show(ex.ToString());
// Hata mesajı ver.
}
finally
{
myClassDAL.Dispose();
// Sınıfı sonlandır.
}//end
try-catch-finally
}
else
{
MessageBox.Show("Ayar
dosyasından bağlantı cümlesi okunamadı.");
}//end
if
}
|
Makalemin yararlı
olması dileklerimle, hoşçakalın...
Makale:
C# ile Veri Erişim Katmanı (Data Access Layer) Geliştirme ADO.NET ve SQL Süleyman Payaslı
|