evcil.net noktanın egemenliği

3008 / 020

Command (Komut) Nesnesi

Command nesnesi, veri kaynaklarına karşı icra edilecek komutları temsil eden ADO.NET
nesnesidir. ADO'daki Command nesnesi ile benzer özelliklere sahiptir.
Command nesnesi de bir Provider nesnesidir ve temsil ettiği komutları icra
ettirebilmesi için kurulmuş (açık) bir bağlantıya ( Connection nesnesine) ihtiyacı
vardır. Bu nedenledir ki açık bir bağlantıyı, Command nesnesi ile ilişkilendirmeden,
onu bir komut icra ettirmek için kullanamayız.

Command nesnesi bize neler sağlar?

* Direk SQL sorguları yürütebiliriz. (SELECT, INSERT, UPDATE, DELETE ve diğer
DDL komutları CREATE, ALTER, ..
)

* Depolanmış prosedür (Stored Procedure) işletimi yaptırabiliriz.
* Depolanmış prosedürler için çeşitli değer aktarım tiplerinde (INPUT, OUTPUT, RETURN
VALUE
) parametreler bildirebiliriz.
* Yürüttüğümüz sorgu (veya stored procedure) sonucu dönen kayıtlara bir DataReader
nesnesiyle ulaşabiliriz.
* Direk bir tablo adını yazarak tüm kayıtlarını döndürebiliriz.
* Tek bir satır veya tek bir skaler değer döndüren sorgular için iyilenmiş
işletim metodlarını kullanabiliriz.
* Command nesnemizi, bir Transaction nesnesi ile ilişkilendirip ADO.NET seviyesinde
Transaction imkânını kullanabiliriz.

Açıktır ki, Command nesnesi ADO.NET'in hayati bileşenlerinden birisi. Connection
nesnesi sadece, uygulamamamızın veritabanı ile olan canlı ilişkisini temsil ederken,
Command nesnesi bu ilişki üzerinden yürüyen her türlü alış/verişi temsil
ediyor.

Her seferinde tekrarlamak sıkıcı ama, bunun gerekli olduğu da bir gerçek. System.Data.SqlClient
sağlayıcısı ile SqlCommand ve SqlDataReader nesnelerini, System.Data.OleDb sağlayıcısı
ile OleDbCommand ve OleDbDataReader nesnelerini kullanmamız gerekiyor. MS SQL Server
7
(ve üst sürüm) veritabanları için SqlClient sağlayıcısını tercih ediyoruz.
OLE DB desteği olan veri kaynaklarına da OleDb sağlayıcısıyla bağlanmaya
devam ediyoruz. ( Bu iki sağlayıcının isimlerini açık yazmak yerine, Framework sınıf
kütüphanesinde temsil edildikleri aduzayı (namespace) tanımlarını yazmayı yeğledim.
Bilginize.
)

NOT
Bu yazıyı okumadan önce, .NET'te Veri Erişimi
: ADO.NET
ve Connection (Bağlantı)
Nesnesi
başlıklı makaleleri okumanızı salık veriyorum.

Bir Command Nesnesi Oluşturmak
Bir Command nesnesini, parametresiz sınıf yapılandırıcısı (constructor) ile
oluşturmak mümkündür. ( Örneklerimizi tekrardan kaçınmak için sadece SqlClient için
vereceğiz. OleDb için de aynı örnekleri, nesne adlarında ve dahil edilen aduzayında
ufak değişiklikler yaparak kendiniz yazabilirsiniz. )

// nesne referansımızın bildirimi
SqlCommand cmdTest;

// ve referansımıza yeni bir SqlCommand nesnesinin oluşturulması ve bağlanması
cmdTest = new SqlCommand();

Örnek kodda, bir SqlCommand nesnesi oluşturduk, yalnız bu nesneyi bir SqlConnection
nesnesi ile ilişkilendirmedik. Şimdi connNorthwind adında bir SqlConnection nesnemiz
olduğunu varsayalım. Bunu cmdTest nesnemiz ile ilişkilendirelim:

cmdTest.Connection = connNorthwind;

Yürüteceğimiz komutu da CommandText özelliğine atayarak bildiriyoruz.

cmdTest.CommandText = "SELECT * FROM Employees";

Ancak tüm bu yaptığımız işlemleri, tek satırda da yapabilirdik. Çünkü SqlCommand
sınıfı, parametreli yapılandırıcılar da sunuyor. İşte tek satır:

SqlCommand cmdTest = new SqlCommand( "SELECT * FROM Employees", connNorthwind );
// Nesneyi, CommandText ve Connection özelliklerini,
// yapılandırıcıda belirleyerek oluşturduk.

Aslında Command nesnesini oluşturmanın daha pratik bir yolu var. Yukarıda hep SqlCommand
yapılandırıcı metodunu kullandık. Şimdi yapılandırıcı kullanmadan, Connection
nesnesinin CreateCommand() metodu ile Command nesnesi oluşturmayı göreceğiz. Bu
metod, bir SqlCommand nesnesi döndürüyor:

SqlCommand cmdTest = connNorthwind.CreateCommand();

Peki yukarıdaki yöntemle bir SqlCommand nesnesi oluşturduğumuzda farklı olan bir
şey olur mu? Evet. Oluşan SqlCommand nesnesi otomatikmen bağlantınız ile ilişkilendirilmiş
olacaktır. Yani bu örnek için konuşursak, cmdTest nesnesinin Connection özelliği,
connNorthwind bağlantı nesnesine otomatikmen bağlanmıştır.

.NET Framework sınıf kütüphanesindeki çoğu nesnede olduğu gibi Command nesnelerinin
de (SqlCommand, OleDbCommand) bir çok şekilde oluşturulabildiğini gördük. Bunların
tek tek makalelerde anlatılması zordur. Bu tip alternatif yöntemler için başvuracağınız
yegane kaynak .NET Framework SDK Dokümantasyonu olmalıdır. Bu dokümantasyonda,
bir sınıfın "Overload" edilmiş tüm yapılandırıcılarını ayrı ayrı görmeniz ve bilgilenmeniz
mümkündür.

CommandText ve CommandType Özellikleri
Command nesnesinin veri kaynağında icra edilmek üzere göndereceği emir cümlesini,
bir string ifade olarak CommandText özelliğine atıyoruz. (Veya az önce belirttiğimiz
gibi parametreli yapılandırıcıda iken bildiriyoruz.)

cmdTest.CommandText = "SELECT * FROM Employees";

Ancak bu emir ifadesinin nasıl yorumlanacağı da önemlidir. Bir komut üç tipten birinde
yorumlanabilir: 1 - SQL ifadesi olarak, 2 - Depolanmış prosedür çağrısı olarak, 3
- Direk tablo adı olarak.
Bunlar arasında ilk belirttiğimiz SQL ifadesi
(Text), komutun öntanımlı tipidir. Komut tipini değiştirmek için Command nesnesinin
CommandType özelliğini kullanıyoruz. Bu özellik, System.Data.CommandType sıralaması
(enumeration) tipinde bir değer alıyor.

// Dahil etmeniz gereken aduzayları: System.Data ve System.Data.SqlClient

cmdTest.CommandText = "SELECT * FROM Employees";
// Tip : SQL İfadesi (varsayılan budur.)
cmdTest.CommandType = CommandType.Text;

//-------
cmdTest.CommandText = "Ten Most Expensive Products";
// Tip : Stored Procedure çağrısı
cmdTest.CommandType = CommandType.StoredProcedure;
//-------
cmdTest.CommandText = "Customers";
// Tip : Direk tablo ad(lar)ı (birden fazla tablo virgüllerle ayrılarak belirtilirse
tablolar katıştırılarak ("join" edilerek) döndürülür.)
cmdTest.CommandType = CommandType.TableDirect;

/*
Açıklama: Örneklerimizdeki SQL sorguları ve depolanmış prosedürler Microsoft'un
örnek veritabanı Northwind baz alınarak yazılmaktadır. Bu nedenle, SQL Server'daki
Northwind veritabanının yapısına ve nesnelerine göz atmanız yararlı olacaktır.
*/

Yukarıda verdiğimiz komutlar, parametre istemeyen komutlardı. Ama çoğunlukla yürüteceğimiz
sorgu veya prosedür için parametre kullanma ihtiyacı doğacaktır. Örneğin bir tablodan
belirli bir kritere uyan kayıtların seçilmesi durumunda komutla beraber parametre
aktarımı gerekecektir. Bunun en kestirme yolu, komut metnini parametrelerle beraber
yazmaktır elbette:

string ulke = "Germany"; // Bu değerin kullanıcıdan alındığını varsayalım
string strSQL = "SELECT * FROM Customers WHERE Country='" + ulke + "'";
cmdTest.CommandText = strSQL;

Bu komut güzelce çalışacaktır. Ancak burda durum çok basittir. Çoğunlukla daha karmaşık
sorgularla karşılaşacağız. Parametre listesinin uzadığı komutlarda, bu tip bir "concatenate"
işlemi gerçekten çok zor ve zahmetli olacaktır. Depolanmış prosedürlerde ise durum
daha ciddidir. Çünkü depolanmış prosedürler, farklı parametre tiplerini desteklemektedirler.
Ve parametreler için veri tipleri belirlenmektedir (sayısal, ondalıklı, para, karakter,
..
). İşte parametreler ile ilgili tüm bu ayrıntılı bilgiyi ifade edebileceğimiz
bir yapıya ihtiyaç vardır: Parameter nesnesi. Parameter nesnesi, bağımsız bir parametreyi
temsil eder. Öte yandan Command nesnesinin Parameters adında bir kolleksiyon özelliği
vardır. Ve tahmin ettiğiniz gibi, bu kolleksiyona komut metni ile ilişkilendirilmiş
parametrelerin eklenmesi gerekiyor.

Parametreler ile ilgili bahsi, sadece bu konuya tahsis edilmiş farklı bir yazıda
tekrar açmak üzere burada kapatıyoruz.

Komutu İcra Ettirmek
Bir Command nesnesine yaptıracağımız nihai iş, temsil ettiği komutu icra ettirmektir.
Yalnız komutu icra ettirme noktasına gelmek için Command nesnesinin buna hazır olduğundan
emin olmalıyız. Açalım. Command nesnesi bir Connection nesnesiyle ilişkilendirilmiş
olmalıdır. Bu yetmez; Connection nesnesinin temsil ettiği bağlantı açık olmalıdır.
Command nesnesinin CommandText özelliğine icra edilecek komut belirtilmelidir ve
gerekiyorse CommandType özelliği ayarlanmalıdır.

Eğer yukarıdaki hazırlık aşamaları tamamlanmışsa, Command nesnesinin ifade ettiği
komutu kolaylıkla icra ettirebiliriz (execute). Ancak ADO.NET, ADO'dan
farklı olarak, sorgudan dönecek sonuç için özelleşmiş (ihtisaslaşmış) 4 ayrı Execute
metodu sunmaktadır:

ExecuteReader() : Bu metod kayıt döndürecek komutlar için özelleşmiştir. İşletimi
sonucu kayıt setini ifade eden bir SqlDataReader nesnesi oluşturur. SqlDataReader
nesnesi kapanana kadar, bağlantı üzerinde komut yürütülemez.

ExecuteNonQuery() : Veri seti döndürmeyen komutlar için özelleşmiştir. Dönüş değeri,
sorgunun işletiminden etkilenen kayıtların (records affected) sayısıdır.

ExecuteScalar() : Sorgu sonucu tek bir değer dönecekse bu metodu kullanmamız daha
uygundur. Örneğin bir kümeleme (aggregation) sorgusunda.

ExecuteXMLReader() : Sorgu sonucu bir XMLReader nesnesi oluşturur.

Bundan sonraki DataReader konulu yazımızda, ExecuteReader() metodu üzerinde ayrıntılı
olarak konuşacağız. Şimdilik basit bir örnekleme yapalım:

SqlCommandDeneme.cs
using System;
using System.Data;
using System.Data.SqlClient;

namespace Makaleler
{
public class KomutIcraDenemeleri
{
public static void Main()
{
// referans değişkenlerimiz
SqlConnection connNorthwind;
SqlCommand cmdTest;
SqlDataReader dtrdTest;

// bağlantı ve komut nesnelerimizi oluşturalım
connNorthwind = new SqlConnection();
cmdTest = new SqlCommand();

// bağlantı cümlesi verip, Northwind ile aktif bir bağlantı kuralım
connNorthwind.ConnectionString = "Integrated Security=SSPI; Database=Northwind;";
connNorthwind.Open();

// komutu, canlı bağlantımız ile ilişkilendirelim
cmdTest.Connection = connNorthwind;

// bir stored procedure çalıştıracağız
cmdTest.CommandText = "Ten Most Expensive Products";
cmdTest.CommandType = CommandType.StoredProcedure ;

// kayıt döneceği için ExecuteReader() kullanıp

// bir SqlDataReader nesnesi oluşturalım
dtrdTest = cmdTest.ExecuteReader();
// konsola göstermelik yazılar..
Console.WriteLine("ExecuteReader() denemesi: ");
// DataReader ile kayıtlar arası forward-only, read-only gezinti
while ( dtrdTest.Read() )
{
Console.WriteLine("Birim fiyat : {0}", dtrdTest["UnitPrice"]);
}

// DataReader'in bağlantı ile ilişkisini keselim
dtrdTest.Close();

Console.WriteLine("
");

// sadece tek değer döndürecek bir sql sorgusu
cmdTest.CommandText = "SELECT Count(*) FROM Employees";
cmdTest.CommandType = CommandType.Text ;
Console.WriteLine("ExecuteScalar() denemesi: ");
// ExecuteScalar ile işletip yazdıralım
Console.WriteLine("Çalışan sayısı : {0}", cmdTest.ExecuteScalar().ToString());

// Bağlantıyı (kesinlikle) kapatalım.
connNorthwind.Close();

}
}
}

Komut satırından derleme komutu:

csc /reference:System.dll,System.Data.dll SqlCommandDeneme.cs


Ve görünen:

deneme width="297" />

Bitirirken...
Bu yazıda, ADO.NET'in hayati bileşenlerinden Command nesnesini inceledik.
Örneklerimizi SQL Server .NET sağlayıcısı tarafından sunulan nesneler üzerinde
verdik. Kodların ufak değişikliklerle OLE DB sağlayıcısının nesnelerine uyarlanmasını
da size bıraktık. Bundan sonraki durağımız DataReader nesnesi olacak.

İyi çalışmalar.

Yazan: Muhammed C. Tahiroğlu

No description. Please complete your profile.
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment


No trackbacks yet.

Sayfalar

Kısımlar

Desteklediklerimiz

Ay bazında arşiv

Haberleşme