evcil.net noktanın egemenliği

809 / 080

Türkçe Hâl Ekleri’ni Programatik Olarak Eklemek

Türkçe'nin İngilizce'ye göre önemli bir farkı var: çekim ekleri. Türkçe'de ismin hâllerine çekim ekleri vasıtasıyla geçiş yapılıyor. Misâl; yalın hâli "armut" olan bir kelimenin "gösterme" hâlini oluşturmak için sonuna -i çekim ekini koyuyor ve biraz çeki düzen veriyoruz: "armudu". "Çıkma" hâli için neticemiz: "armuttan".

Programcılar için parametrik Türkçe ifadeleri, programatik olarak çekimlemek İngilizce'ye göre biraz efor isteyen iş. İngilizce'de "x" kelimesi "of x" diye çekimlenebilirken biz kelimeye bir ek ilave edip bir de sesli uyumlarını, sessiz benzeşmelerini dikkate almak zorunda kalıyoruz.

Yıllardır bu meşakkatli yola girmektense hep cümleleri uzatarak çözümü geçiştirdik: "Ahmet'in profiline göz atın" demek yerine "Ahmet adlı kullanıcının profiline göz atın" deyip yanyoldan dolaştık.

Bu yazıda haberini vereceğimiz ufak C# sınıfı "Türkçe Hâller", bu kronik arızayı giderme maksadı taşıyor. Kodunuzun içerisine ekleyip doğrudan kulllanabileceğiniz basitlikte. Basit bir matematikle kelimelere uygun eki eklemeye çalışıyor.

Kullanımı gayet basit:

string result = TurkceHaller.Uygula("Ahmet", TurkceHaller.IsminHali.Yonelme);

Herhangi bir veri kaynağı kullanmadığı, sadece algoritma olduğu için isim/sıfat tamlamalarında %100 başarılı olamayan C# sınıfını aşağıdaki proje sayfasından indirebilirsiniz.

http://code.google.com/p/turkcehaller

1104 / 080

Uzaktaki GAC’ı Kurcalamak

Bugünkü makalemiz, GAC üzerine. Nâm-ı diğer "Global Assembly Cache". Âşina olmayanlar için ufak bir girizgâhımız (iştah açıcı) olacak.

GAC Nedir?

.NET'in çıkış noktasını hatırlayınız. Windows'un birincil bileşen yapısına deva olarak ilan edildiği günleri hatırlayınız. O günlerde artık uygulamaların Registry'ye ihtiyaç duymadığı, XCOPY ile kopyalanarak eşeysiz üreyebildiği ve ürediği her yerde de kendi başına çalışabildiği söylenmişti. .NET hayatımıza, kendi bilgisini (metadata) üzerinde taşıyan "assembly"leri kazandırmıştı. Bir assembly, kendini tarif etmek için başka bir varlığa ihtiyaç duymuyordu. Versiyonu, kültürü, benzersiz anahtarı üzerindeydi. Assembly'ler bu özelliklerinden dolayı, birbirine karışmadan çalışabiliyordu. Herkesin kullanacağı ortak assembly'leri birbirine karışmadan atacağımız yer ise tam orasıydı işte: GAC.

GAC, ortak assembly'leri bulunduran özel bir klasör yapısı. %SYSTEMROOT\%assembly deyincesi çıkan dümdüz liste biraz kandırıyor bizi. Arka planda daha karmaşık bir dizinleme yapısı var ve atılan her assembly'yi ayrıntılı olarak depoluyor.

GAC Nasıl Yönetilir?

GAC,

  • .NET 1.1 ve .NET 2.0 için ayrı ayrı sunulan yapılandırma snap-in'leriyle:
    gac1
  • Gacutil.exe isimli ufak bir konsol programcığıyla:
    gac2
  • Windows Explorer'da assembly klasörü üzerine giydirilmiş "shell extension" aracılığıyla:
    gac3

yönetilebilir.

GAC'ı yönetmekten kasdımız, içine yeni assembly'ler atıp, mevcutları silebilmek vs.dir.

Bu alternatiflerden ilk ikisi Microsoft SDK'larıyla bilgisayarımıza yüklendiği için üretim ortamı bir makinede yokluğu hissedilecek şeylerdir. O durumda başvuracağımız çözüm sonuncu maddeki Windows Explorer olacaktır.

Hepsinden önemlisi bu saydığımız maddelerin hepsi yerel makinedeki GAC'ın yönetimini sağlıyor. Bir makinenin GAC'ını kurcalayacaksak ve illaki bu aletleri kullanacaksak mecburen makineye giriş yapıp üzerindeki bu araçları çalıştırmamız gerekiyor.

İşte mesele de bu. Neden uzaktaki makinenin GAC'ına müdahale edemiyoruz?

"Deployment" Öyküleri

Genelde uzaktaki bir sistem üzerine assembly'lerimizin dağıtımını yapıyorsak ve bu sistemin de GAC'ını kullanmak istiyorsak az önce "mesele" dediğimiz noktaya gelmişiz demektir. Elimizdeki assembly'leri şu uzaktaki makinenin GAC'ına nasıl atacağızdır? Hep gidip RDP ile masaüstüne bağlanıp el ile gacutil mi çalıştıracağızdır? Ya da sürükle bırak ile C:WindowsAssembly'ye dosya mı atacağızdır?

Microsoft buna bir şey yapması lazım değil midir?

Eğer meseleyle ilgili bir "arama motoru" tecrübesi yaşarsanız, size MSI yapmayı tavsiye olunur. İşiniz gücünüz yok, her çıkacağınız assembly için kütür kütür MSI yapacaksınız dostlar. Bu çözüm sizi tatmin ediyorsa yazının devamını boşverin.

Ya Remote Gacutil?

Yok böyle bir şey. Olmalı ama yok.

Ancak biraz kafa yorunca, uzaktaki makinede komut çalıştırma konseptinden gacutil'i tetikleyebileceğimizi buluruz. Bunun için piyasaya doğru bir salınım yaptığımızda en adam akıllı aracın harikalar diyarı SysInternals'ın PsExec'i olduğunu idrak ediyoruz.

Uzakları Yakın Eyleyen Program: PsExec

PsExec ile yeterli haklara sahip olduğunuz bir makine üzerinde komut işletebiliyorsunuz. Bu aleti kullanarak, karşı makinenin üzerinde gacutil'i tetikleyip assembly listesini düzenleyebiliriz ve güncelleyebiliriz demektir. Tam olarak bir Remote Gacutil yazmayı başaramasak da ona yaklaşabiliyoruz. Ne mutlu!

gac4

Gerisi kodlamayı seven programcılara kalmış. Yazsınlar kendi GAC-deployer araçlarını ve oturdukları yerden keyifle "deployment" yapsınlar. Microsoft, eminim zaman içerisinde MSI'dan daha makul çözümler de sunacaktır. O sunana kadar bizim yan yolumuz (workaround) da bu olsun.

Hadi bakalım. GAC ile.

1803 / 080

Lambda Deyimleri (Lambda Expressions)

C# 3.0 ile .NET dünyasına giriş yapan bu terim aslında epeyce akademik derinlikli bir geçmişe sahip. Meselenin odağımız dışında kalan bu tarafına merak duyanları Wikipedia maddesine şutlayarak devam ediyoruz.

Lambda'yı pat diye anlatmak yerine adım adım gidelim diyoruz, kabul ederseniz. Sıramız şöyle:

  • Delegate yapısı
  • Anonim Metodlar
  • Lambda deyimleri

Delegate Yapısı (C# 1.0)

Delegate (delege) yapısı, tipli fonksiyon işaretçisi olarak tanımlanıyor. Ama bu tanım gayet soğuk durduğu için biz başka bir tanım verelim. Nasıl ki sayılar için int, long; karakterler için char, string vs. gibi veri tipleri tanımlanmışsa .NET dillerindeki "metod" yapılarının da tipi tanımlanmış. Bir metod, parametre listesine ve dönüş değerine göre bir "tip" yani bir delegate ifade eder.

Örneğin :

int KareAl(int x) {   return x * x; } 

Bu metodun tipini yani delegesini yazalım :

delegate int KareAlanFonksiyon(int x);

Ne güzel!

KareAl tek bir fonksiyon olurken, KareAlanFonksiyon bizim için bir int alan ve int dönen fonksiyonların ortak tipi oldu.

Yukarıda bir delegeyi sadece tip olarak tanımladık. Şimdi bu delegeyi canlandıralım da işe yarasın:

KareAlanFonksiyon golgeKareAl = new KareAlanFonksiyon(KareAl);

En başta tanımladığımız gövdesi olan komple bir metod ile canlı bir delege oluşturduk. Tahmin edebileceğiniz gibi bu satırdan sonra golgekareAl(2) çağrısı bize 4 verecektir. Bu satırı şöyle de yazabilirdik kısaca:

KareAlanFonksiyon golgeKareAl = KareAl;Console.WriteLine(golgeKareAl(2));

Anonim Metodlar (C# 2.0)

Adı sanı belli olmayan, direk gövdesini yazarak oluşturduğunuz formalitesi az olan metodlardır. Anonim metodları delegate mahfuzuyla tanımlarız.

Yukarıda hâzır bir metodu (KareAl) kullanarak delege örneği oluşturmuştuk. Şimdi bir adet daha delege örneği oluşturalım fakat metodumuz o anda yazdığımız bir anonim metod olsun:

KareAlanFonksiyon golgeKareAlAnonim = delegate(int x) { return x * x; };

Gidip KareAlanFonksiyon tipiyle uyuşan bir metod yazmak yerine o anda sadece gövdesini yazarak bir metod tanımlamak güzel bir kolaylık. Dikkat edilmesi gereken, delegate mahfuzundan sonra parantez içerisinde girdi parametreyi aynen tanımlamamız.

Lambda Deyimleri (C# 3.0)

C# dilinin üçüncü versiyonu, delegelerin kullanımı için lambda boncuğunu getirdi. Nihâi amaç LINQ'ya hizmet etse de biz de bu dil boncuğunu her yerde rahatlıkla kullanabiliriz. Boncuk dediğimiz şeye teknik literatürde syntactic-sugar deniyor. İşlevsel bir yenilik katmadan sadece sözdizimi hoşlaştıran şeyler demek.

Lambda'nın hoşluğuna bakalım:

KareAlanFonksiyon golgeKareAlLambda = delegate(int x) { return x * x; };

deyimi oluyor size:

KareAlanFonksiyon golgeKareAlLambda = (int x) => { return x * x; };

Yeter mi? Yetmez:

KareAlanFonksiyon golgeKareAlLambda = (int x) => x * x; 

Eğer tip otomatik olarak sezilebiliyorsa bu da yetmez:

KareAlanFonksiyon golgeKareAlLambda = x => x * x; 

Yetsin buraya kadar. Boncuk daha fazla ileri gidemiyor.

Evet dostlar, şahit olduğumuz gibi delege örneğini az ve öz bir ifadeyle oluşturabiliyoruz artık. Örnek istediğinizi duyar gibiyiz. Hadi o zaman.

Örnek Mahallesi

var helvaMalzemeleri = new[] { "şeker", "un", "yağ" };
var malzemeVarMidir = helvaMalzemeleri.Any(malzeme => malzeme == "yağ");
Console.WriteLine(malzemeVarMidir); // True yazar

Lambda kullanalım diye suyunu çıkarmışız değil mi? Hem kendi kendine tiplenen diziler hem kendi kendine tiplenen lokal değişkenler (var) hem lambda ve hem de helva. Helva dışında hepsi C# 3.0 özelliği.

Hepinize kolay gelsin.

Lambda ile.

Kısım: C# Yorum yok
1801 / 080

Seyreyle Gönül .NET Framework Kodunu

"Debug etme" keyfini duydunuz mu hiç?

Bir yan bilgi:

Yazılımcılar, kullandıkları araçlar tamamen teknik terimler içerdiğinden, Türkçe eylemler ile birbirine girmiş lafları çok kullanırlar ve hatta kullanmayı da severler.

"Brawzır'ını aç" veya "prapırti kullan" gibi laflar çok döner dolaşır. "Dibag etmek" de öyle bir kavramdır.

Bir yazılımcının "dibag'ta kodu var"ken aklı başka bir şey almaz.

Keyifli iştir "debug". Yazılan kodun sicim gibi akmasıdır, perde önünde. "Code Review" denen toplu ayinlerde müridler hep beraber "debug" eylerler ki tadına doyulmazdır.

Debug Keyfine Limon Sıkmak

"Debug" esnasında .NET nesnelerinin üzerinde eğleşmeden geçerdik. O oturumlarda sadece kaynak kodu elimizde olan şeylerin içine dalabiliyorduk.

Şimdi Microsoft, güzel bir adım attı gönlümüze doğru. Debug keyfimiz, .NET kodunun içinde de devam edecek bundan böyle.

Kod Okur-Yazarlığı

.NET koduna müracat amaçlı bakmanın mümkün hâle gelmesi, kod okur-yazarlığı meselesini de gündemimize taşımış olacak.

Usta kodcular bilirler ki, kod okumak, yazmak kadar önemlidir. İyi bir kodcunun hem okuması hem de yazması güçlüdür. Okuması zayıf bir kodcunun, aylar sonra kendi yazdığı kodu bile kavrayamaması meselenin ehemmiyetini fehimlerimize çakmaktadır.

.NET kodunu seyretmek, yetişmekte olan kodcu adaylarına kod nasıl okunur-yorumlanır ve düzgün kod nasıl yazılır konularında güzel bir ders olacaktır.

.NET kodu çok mu düzgündür diye muhalif bir ses hep çıkacaktır. Düzgündür. En azından yetişmekte olan kodcu için tertipli, açıklamaları yazılmış, "self-documented" ve "best-practise"ler ihtiva eden bir kod kümesine "debug" vesilesiyle göz atmak mükemmel bir fırsattır.

Yetişmiş kodcu için de, daha önce Reflector mucizesi ile baktığı kodları, ona gerek kalmadan ("debug" amaçlı yorumlarıyla) canlı takip etmek mükemmel bir fırsattır.

Sonuçta bu olay, fırsat oğlu fırsattır; fazla uzatmayalım.

Nasıl ve Nerede?

Bu soruyu, ingilizce kaynakları Türkçe'ye birebir aktaran muhtelif kaynaklara sorsanız ya da doğrudan gidip işin mühendislerinden okusanız daha iyi olur efendim.

Nasıl kurulacağını Shwan Burke, güzel güzel anlatmış.

Kayda değer birkaç not:

  • Şimdilik kütüphanelerin tüm kodlarını indirmek mümkün değil, yakında mümkün olacak.
  • Kodların lisansı "Microsoft Reference License"; sadece okuma amaçlı, kurcalamaya müsade yok.
  • Bu olay Microsoft'un "Open Source" rüzgarında bir orta yol bulmaya çalıştığını gösteriyor.

Teşekkürler tüm "Open Source" .NET kodcuları.

Haydi, başlasın "debug"lar!

YENİ - Paket Yapalım mı?

http://www.codeplex.com/NetMassDownloader adresinden tüm kaynak kodları indirebileceğimiz uygulamayı Kerem Küsmezer iletti. Ellerine sağlık.

2511 / 071

ORM’de Su Bulanık

Evet, anladık: kimse artık hart hurt SQL yazmak istemiyor. Zaten sunucu tarafında karmaşık SP yazma devrini de çoktan bitirmiştik. Vaktidir o zaman yeni moda işlere girişmenin. Değil mi dostlar?

Camiadaki yeni temayül, kod üreteçler kullanmak ve ORM kütüphaneleri ile ilişkisel verileri konforlu biçimde, SQL'e bulaşmadan manipule etmek. Bu eğilim Java camiasından bizim camiaya naklolmuştur, kabul.

Yalnız bu temayül artık doruk noktasına ulaştığından olsa gerek, ortalık ORM'den geçilmiyor. Şu listeye bir bakınız:

  • .NET Persistence
  • BBADataObjects
  • DataObjects.NET
  • Data Tier Modeler for .NET
  • DotNorm
  • Eldorado.NET
  • Enterprise Core Objects (ECO™)
  • Entity Broker
  • eXpress Persistent Objects for .NET
  • FastObjects.NET
  • JC Persistent Framework
  • LLBLGen Pro
  • ModelWorks
  • Nhibernate
  • Nolics.NET
  • Norm
  • Norpheme
  • ObjectBroker
  • ObjectSpaces
  • ObjectSpark
  • Objectz.NET
  • OJB.NET
  • OPF.Net (Object Persistent Framework)
  • ORM.NET
  • Pragmatier Data Tier Builder
  • RapTier
  • Sisyphus Persistence Framework
  • TierDeveloper
  • Bob.NET
  • ObjectPersistor.NET
  • Genome

En eskileri belki Nhibernate ama bu kalabalık, insanın üzerinde "akşam üstü İstanbul trafiği" etkisi oluşturuyor ve iyiyi-kötüyü ayırt ettirmez oluyor.

Bu kalabalık ürün listesi arasında ticari olanlar da var ama genel itibariyle açık kodlu. Açık Kod rüzgarının .NET camiasında artık esip gürlediğinin bir delili bu liste.

Ya MS cephesi?

Microsoft'un elinin armut toplamadığını tahmin edebildiniz: o da ADO.NET Entity Framework ve yepyeni bir sorgulama yapısı olarak LINQ kartlarını açtı. İşin garibi herkes çok beğeniyor MS'in yaptıklarını. Microsoft bu LINQ işini o kadar ciddiye alıyor ki, C#'ı sırf bu işe destek için güncelliyor. Son günlerde "her şey linq için".

LINQ emekleme sürümünde henüz. Performans darboğazı var. Ama koşmaya başladığında, şu yukarıdaki listenin LINQ entegrasyonu yapmaktan başka çıkar yolu görünmüyor.

Netice

  • Halkın SQL'den kurtulalım çırpınışları yerindedir, desteklenmelidir.
  • ORM karmaşasına (hele de ticari olanlarına) pek dalmamak lazımdır.
  • "Linq to SQL" insanı cezbediyor, bir an evvel uygulamak lazımdır:
    • .NET 2.0 uygulamaları öntanımlı olarak LINQ desteklemiyor ama LINQ kullanan bir kütüphaneyi kullanabilir.
    • .NET 3.5'ta LINQ kullanmayanı dövüyorlar.
  • Performansın kritik olduğu uygulamalara, LINQ takoz olacaktır.
2011 / 070

Visual Studio 2008 RTM

Bir süre "Orcas" olarak dillendirilen yeni bebek üretime hazır hâle geldi ve MSDN üyelerine sunuldu. Visual Studio 2008 gelişmiş bir geliştirme platformu. Yanında da .NET Framework 3.5 sürümünü getiriyor.

Bir bakalım ne yenilikler ihtiva ediyor bu "bebek":

- "Eskiler Alırım!"; eskimiş VS kullanıcıları, uygulamalarını aynen VS 2008'de geliştirmeye devam edebilirler. Zira IDE, çok-hedeflilik diye çevrilebilecek multi-targeting özelliğini hâiz. Yani VS 2008'i açıp .NET 1.1 veya .NET 2.0 sürümü için uygulama yazabiliyorsunuz. Böylelikle framework sürümü ile IDE sürümü birbirine bağımlılıktan kurtulmuş oldu.

- Windows Presentation Foundation (WPF) için dâhili tasarım aracı. VS 2005 için eklenti olan bir şeydi, şimdi ürünün bir parçası.

- Bünyeye gömülü olmazsa olmaz AJAX. Tam anlamıyla JavaScript kod tamamlama (intellisense) ve hata ayıklama (debugging) imkânı.

- Debug esnasında .NET Framework kaynak kodunun içine dalış. Hâni Scott bahsetmişti.

- Ve tabî ki veriyle uğraşmanın yeni adı: Linq to SQL. Daha henüz emekliyor bu bebek ama 2010'un sürüm vaktinde olgunlaşacağı vaad edilmiş.

MS yolundaki geliştiricilere hayırlı olsun efendim.

Aboneler buraya: http://msdn2.microsoft.com/en-us/subscriptions/default.aspx

Tümleyenler şuraya: http://www.microsoft.com/express/download/

Kısım: C# Yorum yok
1911 / 020

C# ve OpenGL

OpenGL (Open Graphics Library - Açık grafik kütüphanesi), mevcut OpenGL
destekli grafik donanımınızın sağladığı olanaklardan, uygulamalarınızda sonuna kadar
faydalanabilmeniz için kullanıcıya, kolay anlaşılabilir ve kullanılabilir fonksiyonlar
sağlayan endüstri standartı haline gelmiş bir grafik kütüphanesidir.

1111 / 020

.NET Üzerinde Kriptografi

Bugünlerde bilgisayar dünyasında en çok konuşulan konulardan biri kriptografi,
yani şifreleme. İki tarafın kulak misafiri kaygısı olmaksızın haberleşmelerini
sağlayan bu teknoloji, özellikle son birkaç yılda İnternet''in yaygınlaşmasıyla
önem kazandı. .NET platformu üzerinde gelistirdiğiniz uygulamaları nasıl daha güvenli
hale getirebileceğimize bu yazımızla kısa bir başlangıç yapıyoruz.

909 / 020

DataReader Nesnesi

Önceki yazımızda
bahsettiğimiz gibi Command nesnesi, veri kaynağına karşı yürütülen ifadeleri (emkomutları/em)
temsil ediyor. Genellikle sorguları, bir veri seti döndürmek amacıyla işletiriz.

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.

Sayfalar

Kısımlar

Desteklediklerimiz

Ay bazında arşiv

Haberleşme