Bu yazımızda SqlCommand ve SqlDataReader nesnelerinin kullanımını göreceğiz.Bağlantı yaptığımız veritabanı üzerinde sorgu çalıştırmamızı sağlayan sınıf SqlCommand sınıfıdır.
SqlCommand Nesnesi
SqlCommand nesnesi sayesinde bağlantı yaptığımız veritabanı üzerinden sorgu çalıştırabiliriz.Sorgunun tipine göre(select,insert,update,delete) çalıştırma çeşitliliği gösteriyor.
Şimdi bir SqlConnection nesnesi oluşturup veritabanı bağlantısı yapalım.Ben kendi SQL serverımda Northwind tablosuna bağlantı kuracağım(SqlConnection nesnesine bir önceki yazımda değinmiştim.)Ardından SqlCommand nesnesi oluşturalım.
SqlConnection baglanti = new SqlConnection("Server=GENÇAY-GENÇAY;database=Northwind;Trusted_connection=true;");
baglanti.Open();
SqlCommand cmd = new SqlCommand("Select * from Personeller",baglanti);
baglanti.Close();
baglanti.Dispose();
Yukarda gördüğünüz gibi SqlCommand nesnesinin constructorına bir SQL sorgusu birde SqlConnection tipindeki baglantı referansı yazılmış.Öncelikle şunu bilmeliyiz.SqlCommand nesnesinin çalıştıracağı sorgu hangi bağlantı üzerinden çalışacaktır.SqlCommand ımıza bu bağlantıyı göstermemiz gerekiyor.Yukardaki constructor da yaptığımız gibi sorgudan sonra bağlantıyı verebilirsiniz.Ya da aşağıdaki yolları seçebilirsiniz.
SqlCommand cmd = new SqlCommand(); cmd.CommandText = "Select * From Personeller"; \\ CommandText özelliğine çalıştıracağımız sorguyu yazarız. cmd.Connection = baglanti; \\ Connection özelliğine ise SqlConnection tipinden olan bağlantımızı gösteririz.
Bağlantı oluşturulduktan sonra sorgumuzu çalıştırmamız(Execute) etmemiz gerekir.Bunun için SqlCommand nesnesinin Execute metodlarını kullanılır.
Bu metodlar şunlardır;
ExecuteNonQuery = Geriye int dönen bir metoddur.Genellikle insert,delete,update sorguları çalıştırılır.Sorgunun çalışması sonucunda kaç kayıt etkilenmiş(T-SQL de @@ROWCOUNT) o değeri int olarak geri döndürür.
ExecuteReader = Genellikle select sorguların da kullanılır.Arka planda sorguyu çalıştırır ve gelen verileri SqlDataReader nesnesine yükler ve bize o nesneyi geri gönderir.Bu sonucu okumamız için SqlDataReader referansına bu sonucu alıp,açık bir bağlantı içinde satır satır okumamız gerekir.
ExecuteScalar = Genelde select sorgularında kullanılır.Verilen sorguyu çalıştırır ve sorgu sonucunda oluşan kayıt kümesinin ilk satır ve ilk sütununu object tipte geri gönderir.
ExecuteXmlReader = Select sorgusunun sonucunu xml formatında XmlReader nesnesine yükleyerek, o nesneyi geri döner.
Şimdi sorgumuzu ExecuteReader ile çalıştıralım ve SqlDataReader nesnesinin kullanımınıda görmüş oluruz.
SqlConnection baglanti = new SqlConnection("Server=GENÇAY-GENÇAY;database=Northwind;Trusted_connection=true;");
baglanti.Open();
SqlCommand cmd = new SqlCommand("Select Adi,Soyadi from Personeller",baglanti);
SqlDataReader dt = cmd.ExecuteReader(); \\SqlDataReader referansına cmd.ExecuteReader() bağlıyoruz.Çünkü cmd.ExecuteReader() bir SqlDataReader nesnesi dönüyor.Yani nesne döndüğü için referansa bu nesneyi tanımlamış oluyoruz.
baglanti.Close();
baglanti.Dispose();
Şimdi SqlDataReader nesnesinden verileri okumayı görelim.
dt.Read();
Read() metodu,dt içinde kayıt kümesinde eğer varsa ilk kaydı okur,sonra imleci eğer varsa sonraki kayıt üzerinde konumlandırır.Eğer okuyabileceği kayıt varsa geriye True,yoksa false döner.
while (dt.Read())
{
MessageBox.Show(dt["Adi"].ToString() + " " + dt["Soyadi"].ToString());
\\Bu döngü dt içindeki kayıt sayısı kadar dönecektir.
\\dt den okuma işlemi dt["Adi"] bu şekilde yapılabilir.Sorgu sonucu gelen kolonun ismini yazabiliriz.Ya da indeks numarasına göre yazabiliriz.
\\dr.GetString(0) + " - " + dr.GetString(1) bu şekildede verileri çekebiliriz.Verilerin tipinin string olduğunu bildiğim için GetString metodunu kullandım.Eğer int olsaydı GetInt32() metodunu kullanırdım.
}
Not : Nesnelerle işimiz bittiği zaman onları Dispose() etmemiz faydalı olacaktır.SqlDataReader ı manuel olarak Dispose etmemiz bazı aksaklıklara yol açabilir.Ancak aşağıdaki şekilde CommandBehavior.CloseConnection eklersek, SqlDataReader nesnemizle işimiz bittiğinde dinamik olarak kendisi dispose olacaktır.
SqlDataReader dt = cmd.ExecuteReader(CommandBehavior.CloseConnection);
Her zamanda DataReader nesnemizi bodoslama döngüye sokmak pek iyi değildir.Önce DataReader nesnemizin içinde veri var mı yok mu onu kontrol edelim eğer varsa döngüye girsin.Bunuda HasRowns özelliği ile kontrol ediyoruz.Eğer kayıt varsa True döner, yoksa false döner.
if (dt.HasRows)
{
while (dt.Read())
{
MessageBox.Show(dt["Adi"].ToString());
}
}
else
{
}
Ek olarak SqlDataReader nesnemizle ilgili performansı çok arttıran bir durumdan bahsedeceğim.Eğer Select sorgusundan tek satır döneceğinden eminsek eğer aşağıdaki işlem performansı arttıracaktır.
Aşağıdaki örnekte sonucu tek satır dönen select sorgusu mevcuttur.
SqlConnection baglanti = new SqlConnection("Server=GENÇAY-GENÇAY;database=northwind;trusted_connection=true;");
SqlCommand cmd = new SqlCommand("Select Count(*),AVG(PersonelId) from Personeller",baglanti);
baglanti.Open();
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection | CommandBehavior.SingleRow);
dr.Read();
MessageBox.Show(dr[0] + " " + dr[1]);
baglanti.Close();
Not : ExecuteReader() metoduna CommandBehavior enum tipinden birden fazla değeri aynı anda verebiliriz(Enumlardan ilerideki yazılarımda bahsedeceğim)Bunun için “|(pipe)” kullanabiliriz.Enum tipten birden fazla değeri aynı anda bu şekilde diğer metodlara da geçirmek mümkündür.
Yukarıdaki kod bloğunda gördüğünüz gibi,cmd.ExecuteReader(CommandBehavior.CloseConnection | CommandBehavior.SingleRow) kodundaki CommandBehavior.SingleRow komutu performansı arttırmaktadır.
CommandBehavior.CloseConnection’un ne olduğunu zaten biliyoruz.CommandBehavior.SingleRow’u açıklayayım.
CommandBehavior.SingleRow : Eğer ExecuteReader() metodunun okuyacağı sonuç kümesi sadece tek satırdan oluşuyorsa,bu özelliği kullanmak performansı artıracaktır.Normalde arkaplanda gelecek olan sonuç kümesi için bir koleksiyon oluşturulur.Veriler okunur ve o oluşturulan koleksiyona yüklenirler.Oradan da bize gönderilirler.Tek satırlık bir veri için bu kadar işleme gerek yoktur.Eğer bu gibi durumlar da bu özelliği kullanmazsak,tek satırlık veri içinde bu işlemler gerçekleştirilecek ve performans düşüşüne sebep olacaktır.Biz bu özellik sayesinde tek dönen verinin tek satır olacağını söylüyoruz ona göre işlemcimizi yordurmuyoruz.