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:

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.
