Yazılımcının Günlüğü | YazilimGunlugu.Com
Arama
Makale Kategorileri
Üye Girişi
Şuanki online üyeler()
Aktif üye bulunmamaktadır.


C# ile Derinlemesine SqlConnection

Yazar: Yasin Sirkecili

Kategori: C#.NET

Eklenme Tarihi: 18.05.2007 19:20:54

C# ile MSSQL 7.0+ veritabanlarina baglanirken kullanacagimiz System.Data.SqlClient.SqlConnection sinifi, Connection String incelikleri, Veriler üzerindeki Yetkinlikler ve Transaction yapisi...

Bu makalemizde SQL 7.0 ve yukarisi veritabanlarina baglanirken kullandigimiz SqlConnection sinifini properties, method ve eventleri ile gözden geçirmeye çalisacagiz.

SqlConnection classi System.Data.SqlClient namespace inden gelmektedir. Bu nedenle öncelikle.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;


satirini ekleyerek SqlConnection imizi kullanabilir hale getiriyoruz.

Daha sonra bu class yardimiyla programimizda kullanabilmek için bir SqlConnection nesnesi türetelim.

SqlConnection baglanti = new SqlConnection();



Simdi SqlConnection la birlikte kullananabilecegimiz ve veritabanına baglanirken bize avantaj, dezavantaj saglayayan propertieslermizi inceleyelim.

Öncelikle bir örnek olmasi açisindan bu baglantimiza ait connection string’imizi yazip daha sonra bu yazdiklarimizi tek tek inceleyelim.

baglanti.ConnectionString = "Data Source=localhost; database=yasindb; uid=sa; pwd=sirkecili; pooling=true; connection lifetime=20; connection timeout=25; packet size=1024;";



Connection String Properties:

Data Source: Baglanacagimiz bilgisayarin adi yada ip numarasini belirtiriz.

Database: Baglanacagimiz database’in adini belirtiriz.

Usser ID(uid): Baglanacagimiz sql veritabanına hangi kullanici adi ile girecegimizi belirtiriz.

Password (pwd):: user id mize ait sifremizi belirtiriz.

Pooling: Database’ e birkere baglanip verileri okuduktan yada yazdiktan sonra database ile olan baglantiyi ya biz sonlandiririz. Ya imleç connection nesnesinin etki alanindan çikinca otomatik olarak sonlandirilir. Yada database ile belli bir süre işlem yapmayinca devreye garbage collectors girerek baglantinin sonlanmasini saglar. Bu tip durumlarda ayni veritabanından ayni yada daha fazla veriyi alırken kullanici performansin üst düzeyde olmasini hatta sanki bellekten okunuyormus gibi olmasini ister. Pooling bu noktada devreye girer ve daha önce database’den alinmis olan verileri çok daha hizli olarak tekrar istemciye gönderimesini saglar. Iki farklı değer alabilir. True olursa aktif, false olursa pasiftir.

Dikkat etmemiz gereken nokta pooling yapisi ayni connection string ile olusan baglantilar için geçerlidir.

Pooling’in özelliginin sagladigi performans katkisini görmek için database ile olan baglantimizi açip kapatarak bir test yapalim.

SqlConnection baglanti1 = new SqlConnection();
SqlConnection baglanti2 = new SqlConnection();




 

 


private void Form1_Load(object sender, EventArgs e)
{
baglanti1.ConnectionString = "Data Source=localhost; database=yasindb; uid=sa; pwd=sirkecili; pooling=true; connection lifetime=10; connection timeout=5; packet size=1024;";
baglanti2.ConnectionString = "Data Source=localhost; database=yasindb; uid=sa; pwd=sirkecili; pooling=false; connection lifetime=10; connection timeout=5; packet size=1024;";
}

private void ac_Click_1(object sender, EventArgs e)
{
DateTime baslangic = DateTime.Now;
for (int i = 0; i < 9999; i++)
{
baglanti1.Open();
baglanti1.Close();
}
DateTime bitis = DateTime.Now;
TimeSpan fark = bitis - baslangic;
label1.Text = fark.TotalMilliseconds.ToString();

}

private void kapat_Click(object sender, EventArgs e)
{
DateTime baslangic = DateTime.Now;
for (int i = 0; i < 9999; i++) {
baglanti2.Open();
baglanti2.Close();
}
DateTime bitis = DateTime.Now;
TimeSpan fark = bitis - baslangic;
label2.Text = fark.TotalMilliseconds.ToString();

}





Gördügünüz üzere pooling özelligi Sql baglantilarimizda performansimiza yüksek düzeyde etkinlik saglamaktadir.

Min pool size: Aktif olabilecek minimum baglanti sayisini belirtir.
Max pool size: Aktif olabilecek maksimum baglanti sayisini belirtir.

Connection Lifetime: Açmis oldugumuz connection’in ne kadar süre aktif olacağını bu özellikle belirleriz.

Connection Timeout: veritabanına baglanirken zaman zaman server tarafli, zaman zaman client tarafli yada diger iletisim problemleri nedeniyle baglantinin saglanamadigi durumlar gerçeklesir. Bu durumlar, Programimizin ne kadar süre içinde veritabanına baglanmasi gerektigini hatta daha açik bir cümleyle… “ne kadar sürede veritabanına baglanamazsa hata verecegini” belirleriz. Default olarak değeri 15sn dir. Eger connection stringde belirtmez isek. 15 sn olarak kabul edilir.

Packet Size: Performans açisindan çok önemli bir kriter olan packet size. Baglantinin kaç bytle’lik paketler halinde veri iletisimi saglayacagini belirtir. Default olarak değeri 8192 byte olup minimum değeri: 512 maximum değeri: 32767 byte yani 32 kb’dir. Alacagimiz verinin büyüklügüne göre seçecegimiz bu değer. Genellikle resim yada benzeri büyük boyutlu içerikler için 32767 text içerikler içinse daha düsük değerleri içermelidir. Baglanti saglanmadan önce connection stringde belirtilmesi gerektigi için


baglanti.Open();
baglanti.PacketSize = 2048;



gibi sonradan belirttigimiz bir kullanimda hata olusturacaktir.

Properties

State: Kod bloklarinda çogu zaman baglantinin ne zaman açilip ne zaman kapandigi belirtmis olsakta kullanıcının işlem yapma zamanini göz önünde bulundurdugumuzda baglantinin durumunu tekrar gözden geçirmemiz gerekir. Örnegin eger baglanti açiksa kullanıcının istedigi işlemi tekrar baglanti olusturmadan daha hizli yapmasini saglayabilir. Yada bunun tam tersi durumlarda kullanici işlem yapmakta gecikmis ise baglantiyi yenilememiz gerektigini bu özellik sayesinde ögrenebiliriz.


SqlConnection baglanti = new SqlConnection();
private void Form1_Load(object sender, EventArgs e)
{

baglanti.ConnectionString = "Data Source=localhost; database=yasindb; uid=sa; pwd=sirkecili; pooling=true; connection lifetime=20; connection timeout=5; packet size=1024; connection lifetime=5;";
baglanti.Open();

}

private void durum_Click(object sender, EventArgs e)
{
if (baglanti.State == ConnectionState.Open)
{
MessageBox.Show("baglanti açik");
}
else {
MessageBox.Show("baglanti kapali");
}


}

private void ac_Click(object sender, EventArgs e)
{
if (baglanti.State == ConnectionState.Closed) // Açik olan baglantiyi tekrar açmak hata mesaji üreteceginden if döngüsüne aldik.
{
baglanti.Open();
}
else
{
MessageBox.Show("Baglanti zaten açik");
}
}

private void kapat_Click(object sender, EventArgs e)
{
baglanti.Close(); }



 

 




State yapsinin ögrenebilecegimiz durumlari söyledir:



a) Broken: Belirtilen baglanti daha önce closed olmus ve daha sonra tekrar açilmistir.
b) Closed: Baglanti kapali durumdadir.
c) Connecting: Baglanti kurulma asamasindadir.
d) Executing: Baglanti üzerinde o anda bir komut işlem görmektedir.
e) Fetching: Veri alisverisi yapılmaktadir.
f) Open: Baglanti Açiktir.

Yazilin ilerleyen bölümlerinde StateChange olayini inceleyecek ve bu olay yardimiyla baglanti durumu degistiginde direkt bilgi alabilecegimizi görecegiz.

ServerVersion: Çalistigimiz database in versiyonunu ögrenmemize yarar. Geriye server’in versiyon bilgisini dönderir.

Örnek kullanim:


SqlConnection baglanti = new SqlConnection();
private void Form1_Load(object sender, EventArgs e)
{
baglanti.ConnectionString = "Data Source=localhost; database=yasindb; uid=sa; pwd=sirkecili; pooling=true; connection lifetime=20; connection timeout=5; packet size=1024; connection lifetime=5;";
baglanti.Open();
}
private void durum_Click(object sender, EventArgs e)
{
if (baglanti.State == ConnectionState.Open)
{
MessageBox.Show("Database version: " + baglanti.ServerVersion);

}
else {
MessageBox.Show("baglanti kapali");
}



 

 



SqlConnection Methods:

ChangeDatabase: Bazi durumlarda baglantimiz açik iken connection stringde belirtilen database’den baska bir database geçmemiz ve ordaki verilere ulasmamiz gerekebilir. Bu durumlarda ChangeDatabase methodu ile ayni serverdaki baska bir database e geçebiliriz. Ancak unutmayalimki bu durumda diger Database’e baglanirken windows authentication yada mssql yetkili kullanici parolasi kullanmamiz gerekir.

baglanti.ChangeDatabase("DigerDatabase");



CreateCommand: Database ile veri iletisimi saglarken kullandigimiz SqlCommand’larda hepimizin genellikle kullandigi

1-) SqlCommand KomutAdi = new SqlCommand("select * from tablo", baglanti);

yada

2-) SqlCommand KomutAdi = new SqlCommand();
KomutAdi.Connection = baglanti;

Gibi satirlar ile… bilirizki hangi SqlCommand’in hangi SqlConnection ile iliskilendirildigini belirtmemiz gerekir.

SqlConnection sinifina ait bu methodlada baglanti açik konumdayken o baglantiya ait yeni bir SqlCommand nesnesi yaratiriz.

Örnek kullanim:

SqlCommand KomutAdi = baglanti.CreateCommand();



Open: Kapali konumda olan baglantinin açilmasini saglar. Dikkat edilmesi gereken iki nokta vardir.

a) Açik olan baglantiyi tekrar açmaya kalkarsaniz hata verir.

b) SQL baglantilarinda baglanti olusurken server’dan cevap alinamamasi gibi durumlar farklı sebeplerden ötürü siklikla karsimiza çikar. Bu yüzden Open methodunun kullanildigi noktalarda try – catch blogu kullanmak yada daha farklı olarak connection timeout süresinden önce hatayi yakalayacak bir timer olusturarak kullaniciyi hata mesaji ile karsi karsiya getirmemek önem teskil eder.

Örnek kullanim:


try
{
baglanti.Open();
}
catch {
MessageBox.Show("baglanti kurulamadi");
}



Close: Açik olan baglantinin kapatilmasini saglar.

Örnek Kullanim:

Baglanti.Close();



Transaction ve Isolation Level’lar:

Transaction database baglantilarinda en önemli yere sahip noktalardan biridir. Database’e bagli iken yaptiginiz işlemlerde olusan local yada server tarafli yada diger iletisim aksilikleri. Yada ayni anda baska bir client’la ayni database’e bagli oldugunuz ve degisiklik yaptiginiz durumlarda olusabilecek birçok hata mevcuttur. Bu gibi durumlarda transaction kullanarak bu olasi hatalardan bazilarinin önüne geçmemiz mümkün olmasada verilerimizin kaybolmasina karsin güvenligini saglamamiz mümkün. Örnek vermek gerekirse;

Varsayalim belli işlemler ile puan topladigimiz bir oyun programladik. Ve oyunumuza nick belirterek girişler saglayabiliyor. Hatta topladigimiz puanlari bu nickler arasinda birbirine göndererek paylasimini da saglayabiliyoruz. Böyle bir hikayede Oyuncu1 nick’i ile topladigimiz 1000 puanin 500’ünü “Oyuncu2” adli nick’e aktariyoruz. Aktarma sirasinda gerçeklesecek bir elektrik kesintisi yada benzeri anlik aksakliklar sonucu Oyuncu1’den çikmis olan 500 puan Oyuncu2’ye varmadan kaybolacaktir.

Ikinci bir varsayimda ise baska birinin size puan transfer ettigi bir durumda sizin sagladiginiz baglantida 1000 puaniniz oldugu görünürken o anda baska biri size puan transfer ediyor. Ancak siz puaninizi 1000 olarak görmeye devam ediyorsunuz. Bu varsayimda ise baglanti saglandiginda veriler üzerindeki yetkinliginizi tanimlamaniz gerekiyor.

Örnek kullanim:



private void durum_Click(object sender, EventArgs e)
{
SqlConnection baglanti = new SqlConnection();

SqlParameter AktarilacakPuan = new SqlParameter();
SqlParameter AktarilacakOyuncu = new SqlParameter();

AktarilacakPuan.ParameterName = "@puan";
AktarilacakPuan.Value = textBox2.Text;

AktarilacakOyuncu.ParameterName = "oyuncu";
AktarilacakOyuncu.Value = textBox1.Text;

SqlTransaction sqltrans = new SqlTransaction(); // Transaction nesnemizi yaratiyoruz
baglanti.ConnectionString = "Data Source=localhost; database=yasindb; User ID=sa; Password=sirkecili; pooling=true; connection lifetime=100; connection timeout=25; packet size=2048;";
baglanti.Open();
SqlCommand ekle = baglanti.CreateCommand(); // baglanti adindaki SqlConnection nesnemizde kullanmak için komut yaratiyoruz.
ekle.CommandType = CommandType.Text;
ekle.CommandText = "update puanlar set puan=puan + @puan where oyuncu=@oyuncu";
ekle.Parameters.Add(AktarilacakPuan);

try
{
sqltrans = baglanti.BeginTransaction(IsolationLevel.ReadCommitted); // ReadCommited olarak çalismasini istedigimiz transaction'imizi baslatiyoruz.
ekle.ExecuteNonQuery();
sqltrans.Commit(); // işlemin başarıyla gerçeklestigini onayliyoruz. Ve böylelikle puan karsi tarafa puan göndermis oluyoruz.
MessageBox.Show("aktarim başarıyla tamamlandi");
baglanti.Close();
}
catch {
sqltrans.Rollback(); // işlemin başarısiz oldugunu belirterek transaction'in basladigi noktaya dönüyor ve puanin gitmemesini sagliyoruz
MessageBox.Show("aktarim gerçeklestirilemedi");
}



Not: verimiz commit olduktan sonra bizden düsmesi gereken puani Önemli olan konunun anlasilmasi düsüncesiyle es geçtim.

Burdaki kodlamada belirttigim

sqltrans = baglanti.BeginTransaction(IsolationLevel.ReadCommitted);



satirindaki isolationLevel dikkatinizi çekmistir. Simdi bu level’larin ne anlama geldigini sirayla inceleyelim.

Chaos: O anda baskasi database üzerinde degisiklik yapiyor ise sizin degisiklik yapmaniza izin vermez.

ReadCommited : Database’e baglandiginizda o anda baskasi degisiklik yapiyorsa onun commit olmus verilerine ulasmanizi. Henüz onaylanmayan degisikliklerini görmemenizi saglar.

ReadUncommited: Baska birini degisiklik yaptigi anda kisinin verileri henüz commit olmamis dahi olsa onlari görüntüleyebilmenizi saglar.

RepeatableRead: Siz verileri okur iken baglanti sağlayan diger Client’larin degisiklik yapmamasini saglarsiniz.

Serializable: Database’deki tüm verileri dondurarak hiçbir satira güncelleneme yapilamamasini ve yeni satir eklenememesini saglar.


SqlConnection events:

StateChange: Bu event yardimiyla connection durumunda bir degisiklik meydana geldiginde istedigimiz bir kod blogunun isletilmesini saglariz. Böylelikle baglanti durumunda bir degisiklik oldugu anda bilgi almamizida mümkün kilmis oluruz.

Bunun için önce baglantimizi olusturacak. Daha sonra bu baglantiya ait bir statechange eventi yaratacak. Ve bu event yardimiyla durum bilgisi degistiginde ekrana MessageBox çikartip durum bilgisinin hangi konumdan hangi konuma geçtigini görünteleyecegiz.

Örnek Kullanim:

SqlConnection baglanti = new SqlConnection(); // baglantimizi olusturuyoruz.

private void Form1_Load(object sender, EventArgs e)
{
baglanti.ConnectionString = "Data Source=localhost; database=yasindb; uid=sa; pwd=sirkecili; pooling=true; connection lifetime=10; connection timeout=5; packet size=1024;";
baglanti.StateChange += new StateChangeEventHandler(durumbilgisi); // kod ile olusturdugumuz sqlconnection nesnemize ait durumbilgisi adinda statechange eventi tanimliyoruz.
}

private void ac_Click_1(object sender, EventArgs e)
{
if (baglanti.State == ConnectionState.Closed) // baglanti kapaliysa...
{
baglanti.Open(); // baglantiyi açiyoruz.
}
}

private void kapat_Click_1(object sender, EventArgs e)
{
baglanti.Close(); // baglantiyi kapatiyoruz.
}

private void durumbilgisi(object sender, StateChangeEventArgs e) // olusturdugumu durumbilgisi eventine StateChangeEventArgs parametresini vererek durum bilgisini gözlemliyoruz.
{
MessageBox.Show("Baglanti " + e.OriginalState.ToString() + " konumundan " + e.CurrentState.ToString() + " konumuna geçti"); // baglanti durumu degistiginde durumu gözlemliyoruz.

}



 



Dikkat ederseniz e.OriginalState ile baglantinin durum degistirmeden önceki halini e.CurrentState’de o anki durumunu yansitmaktadir.


Evet bir makalenin daha sonuna geldik.Umarim yararlı olmustur.
Hepinize mutlu günler dilerim. :):):):)


Iyi çalismalar.
Yasin Sirkecili

Yazar Hakkında Yorum Yok Yorum Yaz Yazara ait diğer Makaleler
Tema
Anket
Visual Studio 2010 Beta 2'yi denediniz mi?


En Çok Okunan Makaleler
En Son Eklenen Makaleler
Soru Merkezinde Bekleyenler
Ana Sayfa | Hakkımızda | Editörler | Yazarlar | RSS RSS | İletişim
Yazılım Günlüğü 2007-2009 © Tüm Hakları Saklıdır.