String İşlemleri – 1
Bu makalemizde sizlere ASP.NET'te metin işlemlerinin nasıl yürüdüğünü elimizden
geldiğince anlatmaya çalışacağız. Hatırlayacağınız üzere ASP/VBScript zamanında
biz bu işlemleri replace, mid, left gibi bazı fonksiyonları kullanarak yapıyorduk,
ASP.NET bu fonksiyonları tamamiyle unutmuş değil, kodlarını VB.NET kullanarak yazanlar
bu fonksiyonları aynı şekilleriyle kullanabilirler ama C# kullanıcıları bu fonksiyonları
kullanamazlar! ASP.NET''de zaten metinlerle olan işlerimizi gerçekleştirebilmemiz
için hali-hazırda bir kaç farklı sınıfımız mevcut.
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.
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ı |
Ö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"; /* |
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 // bağlantı ve komut nesnelerimizi oluşturalım // bağlantı cümlesi verip, Northwind ile aktif bir bağlantı kuralım // komutu, canlı bağlantımız ile ilişkilendirelim // bir stored procedure çalıştıracağız // kayıt döneceği için ExecuteReader() kullanıp // DataReader'in bağlantı ile ilişkisini keselim Console.WriteLine(" // sadece tek değer döndürecek bir sql sorgusu // Bağlantıyı (kesinlikle) kapatalım. } |
|
Komut satırından derleme komutu:
| csc /reference:System.dll,System.Data.dll SqlCommandDeneme.cs |
Ve görünen:
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.
Connection (Bağlantı) Nesnesi
ADO.NET''in programcıya sunduğu veri erişim mimarisinden
href="/post/net-te-veri-erisimi-ado-net/">.NET''te Veri Erişimi :
ADO.NET başlıklı yazımızda bahsetmiştik. Belirttiğimiz gibi, ADO.NET,
bağlantısız veri operasyonlarına ve verinin standart XML ifadesine tam destek
veriyor.
ADO.NET''in veri kaynağıyla canlı ilişkide olan tarafını .NET
Veri Sağlayıcısı oluşturuyor. Bu sağlayıcı, veri kaynağına gönderilecek her
türlü komut, ve ondan dönecek her türlü yanıt için bir köprü vazifesi görüyor.
Tüm bu operasyonlar için, bu sağlayıcının aktif bir bağlantısı olması gerekiyor.
İşte bu bağlantı, Connection nesnesiyle temsil ediliyor. Connection
nesnesi, ADO.NET''in en temel nesnesi.
Her veri sağlayıcısı, kendine özgü
gerçeklenmiş bir bağlantı nesnesi sunmak durumunda. .NET ile gelen OLE DB .NET
sağlayıcısının sunduğu bağlantı nesnesi
class=CodeInText>OleDbConnection. SQL Server .NET veri sağlayıcısının
bağlantı nesnesi ise
class=CodeInText>SqlConnection. Her iki nesnenin de kullanımı genel
olarak aynı. Yazımızda her iki sağlayıcı için de bağlantı örnekleri vereceğiz.
SqlConnection
Microsoft SQL Server 7.0 ve üst
sürüm veritabanlarına erişmek için class=CodeInText>System.Data.SqlClient aduzayı altındaki class=CodeInText>SqlConnection nesnesini kullanıyoruz. Bu bağlantı
nesnesi (daha doğrusu nesneyi sunan sağlayıcı), sadece SQL Server için
tasarlandığı için başka bir veritabanı erişiminde kullanamıyoruz. SQL
Server''in daha alt sürümlerine erişim içinse eskiden olduğu gibi yine OLE DB
kullanılacak. Peki 7 ve üst versiyonlarında neden ayrı bir sağlayıcı kullanmamız
gerekiyor? Aslında böyle bi zorunluluk yok. OLE DB hala bir seçenek. Ancak
veritabanı erişimi gibi masraflı bir işte daha yüksek performans
arzuluyorsak, tercihimiz SQL Server .NET veri sağlayıcısı olmalıdır. Çünkü bu
sağlayıcı, SQL Server ile TDS (Tabular Data Stream) paketleri
seviyesinde, yani SQL Server''in anladığı dilde haberleşiyor. Böylece OLE
DB gibi bir tercümanı direk saf dışı bırakmış oluyorsunuz. .NET
dokumantasyonunda bu durum şöyle çizilmiş:
Uygulamanızı hâlâ
veritabanından bağımsız yapmak istiyorsanız, çok katmanlı mimariyi iyi
planlamalı ve gerçeklemelisiniz. Veya ilerde konularımız arasında olacak class=CodeInText>System.Data aduzayı bünyesindeki sağlayıcılar için
yazılmış arabirimlerden (IDbConnection, IDbCommand, IDataReader, ..) yararlanmak
da bir çözüm olacaktır.
Şimdi SQL Server 2000 üzerindeki ünlü
Northwind veritabanına bağlantı kuracağımız, bir konsol uygulaması
yazalım:
| SqlConnectionOrnegi.cs | |
class=cs_c>// gerekli aduzaylarını bildirelim. // SQL Provider''i System.Data.SqlClient aduzayı temsil ediyor. class=cs_k>using System; using System.Data.SqlClient; namespace Evcil.NET { public class CBaglanti { public class=cs_k>static void Main() { // bağlantı cümlesini oluşturalım. // OLEDB bağlantı cümlelerinden farklı olarak, // Provider değeri belirtilmediğine dikkat edin string sBaglantiCumlesi = "Server=(local); User id=sa; Password=; Database=Northwind"; // SqlConnection tipindeki bağlantı nesnemizi, class=cs_c>// SqlConnection sınıfının, bağlantı cümlesini parametre alan // yapılandırıcısı (constructor) ile oluşturuyoruz. SqlConnection oConn = new SqlConnection(sBaglantiCumlesi); // bağlantımızın kurulması oConn.Open(); Console.WriteLine( class=cs_s>"Northwind ile baglanti kuruldu"); class=cs_c>// .... burda Northwind üzerinde class=cs_c>// istediğiniz operasyonları yaptığınızı varsayalım. // işimiz bitince bağlantıyı "kesinlikle" kapatmalıyız. oConn.Close(); Console.WriteLine( class=cs_s>"Northwind ile baglanti kesildi"); } } } | |
Neler
yaptığımıza biraz daha yakından bakalım. Başlangıçta, konsola yazı yazmak için
gereken class=CodeInText>Console sınıfının bulunduğu class=CodeInText>System aduzayını ve class=CodeInText>SqlConnection sınıfının bulunduğu class=CodeInText>System.Data.SqlClient aduzayını kullanacağımızı
derleyiciye class=CodeInText>using ayrılmış kelimesiyle bildirdik. Bu bildirimi
yapmasak da olur; ama o zaman bahsedilen sınıfları, her seferinde aduzayı ile
birlikte (Fully-Qualified) yazmak zorunda kalırız: class=CodeInText>System.Data.SqlClient.SqlConnection . Hangisi
kolayınıza(!) geliyor?
Kendimize has bir aduzayı ve sınıf tanımı
yaptıktan sonra, bağlantı denememizi, bağımsız (stand-alone)
uygulamamızın giriş noktası (entry point) olacak class=CodeInText>Main() rutinimizde yazacağız. Burda "Bağlantı
Cümlesi" diye bir kavram görüyoruz. Bağlantı cümlesi, OLE DB''den gelen bi
kavramdır. Bir OLE DB sağlayıcısı üzerinden bir veritabanına erişimle ilgili her
türlü detay, daha genel bir ifadeyle bir "bağlantı" ile ilgili her detay
bağlantı cümlesinde ifade edilir. Bu cümle anahtar/değer çiftlerinin (;) noktalı
virgül ile birleştirilmiş halidir. İşte örnek bir bağlantı cümlesi:
style="MARGIN-TOP: 4px; MARGIN-BOTTOM: 4px; MARGIN-LEFT: 4px">Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Northwind;Data Source=127.0.0.1 |
Siz
de kolayca bir OLE DB bağlantı cümlesi oluşturmak isterseniz boş bir metin
dosyasının uzantısını .udl yapın. Dosyanın simgesinin değiştiğini
göreceksiniz. Dosyayı çift tıkladığınızda, "Data Link Properties"
başlıklı sihirbaza benzer bir Windows uygulaması açılacak. Burdaki seçenekleri
kullanarak geçerli bir bağlantı cümlesi oluşturursanız önünüze bir seçenek daha
çıkar: OLEDB bağlantısında, parametre olarak bağlantı cümlesi yerine bu dosyanın
yolunu verebilirsiniz. Böylece bağlantı detayınızı harici bir dosyada saklamış
olursunuz. Ne kadar faydalı olduğu tartışmalıdır.
Şimdi, class=CodeInText>SqlConnection nesnesi için bağlantı cümlesi oluştururken
dikkat etmemiz gereken bir nokta var, ondan bahsedelim. Yukarıda verdiğim
bağlantı cümlesi örneği OLE DB içindi. OLE DB bağlantı cümlelerinde class=CodeInText>Provider anahtarı ile sağlayıcı seçimi yapmamız
gerekiyor. Eğer yapmazsak varsayılan sağlayıcı olan "OLE DB Provider for ODBC
Drivers" i seçmiş oluyoruz. Bu tür bir seçim yapmamızın nedeni OLE DB API
katmanının birbirinden çok farklı veri kaynaklarına erişimi mümkün kılması.
Bunun için de, bizden bağlanacağımız veri kaynağına uygun bir Provider
(sağlayıcı) seçmemizi bekliyor. Ancak class=CodeInText>SqlConnection ile kuracağımız bir bağlantı için
oluşturacağımız cümlede class=CodeInText>Provider anahtarını kullanmıyoruz. Çünkü sadece
SQL Server''e bağlanacağız ve bir "Provider" seçimi yapma hakkımız
yok.
Bağlantı cümlesinde anahtarların sırası önemli değildir. Geleneksel
olsun diye ilk önce class=CodeInText>Server anahtarına bir değer atadık. ( class=CodeInText>Server yerine Data
Source anahtarı da kullanılabilir.) Yerel SQL Server''e bağlanacaksak
anahtara class=CodeInText>"(local)" (veya class=CodeInText>"localhost", class=CodeInText>"127.0.0.1", ..) değerini veriyoruz. Buraya uzaktaki bir
SQL Server''in IP adresini de yazabiliriz. Daha sonra SQL Server Login
bilgilerimizi belirtiyoruz. SQL Server''a iki türlü login olabiliriz. Birincisi
SQL Server Doğrulaması ile. İnternet uygulamaları için en uygun olanı
budur. Bu tür girişte bir kullanıcı adı ve parola belirtiriz. İkincisi ise
Bütünleşik Windows Doğrulaması''dır. Bu seçenekte ise, SQL Server
Windows''a giriş yaptığımız login bilgisine göre doğrulama yapar. Bağlantı
cümlesinde entegre Windows doğrulamasını kullanmak istersek user id ve password
anahtarları yerine class=CodeInText>"Integrated Security = SSPI; " anahtar/değer çiftini
belirtmeliyiz. (veya "Trusted Connection = True;")
Sonra SQL Server
üzerindeki veritabanlarından birini seçmek istiyoruz. Bunun için de class=CodeInText>Database (veya class=CodeInText>Initial Catalog) anahtarını kullanıyoruz. Böylelikle
bağlantı ile ilgili detayları verdiğimiz bir cümleyi oluşturmuş olduk. Bunu bir
string değişkene atadık.
class=CodeInText>SqlConnection tipinde deklare ettiğimiz referansı ( class=CodeInText>oConn), class=CodeInText>SqlConnection''un bağlantı cümlesini parametre alan
yapılandırıcısı ile yarattığımız nesneye bağladık. Bağlantı cümlesini, nesneye
daha sonra da atayabilirdik ama kolaylık olsun diye, daha yapılandırıcıda iken
bu işi hallettik.
alabilecekleri değerler ile ilgili ayrıntılı açıklamayı lokal .NET Framework SDK
dokumantasyonunda veya href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDataSqlClientSqlConnectionClassConnectionStringTopic.asp"
target=_blank>burada bulabilirsiniz.
Bağlantı nesnemizi
oluşturduk. Hafızada (heap''te) bu nesne için bir yer ayrıldı. Ancak tüm bunlar,
"bağlantı cümlesinde" bahsini geçtiğimiz SQL Server veritabanı ile fiziksel bir
bağlantı kurmuş olduğumuz anlamına gelmiyor. Şimdilik sadece niyetlendik. Bu
bağlantının kurulması için bağlantı nesnemizin class=CodeInText>Open() metodunu işletiyoruz. Eğer hiç bir problem yoksa,
bağlantınız kurulacak ve bağlantı nesnemizin class=CodeInText>State (vaziyet) özelliği class=CodeInText>ConnectionState.Open (açık) duruma gelecektir. Artık
veri kaynağı ile oConn nesnesi üzerinden canlı bir bağlantımız vardır ve
sağlayıcının diğer nesneleri ile (SqlCommand, SqlDataReader, SqlDataAdapter) bu
canlı bağlantı üzerinden istediğimiz manipulasyon operasyonlarını
gerçekleştirebiliriz.
Bu yazımızda sadece bağlantı nesnesi üzerinde
odaklanmak istediğimiz için, hiç bir işlem yapmadan bağlantımızı kapatacağız. Bu
iş için de parametresiz basit bir metodumuz var: class=CodeInText>Close(). Veritabanı bağlantısı masraflı (yani sistem
için zahmetli) bir iş olduğundan, işimizi en kısa sürede halledip bekletmeden,
aktif bağlantıyı kapatmayı unutmamalıyız. Eğer bunu unutursak, bağlantımız belli
bir zaman aşımı süresi kadar açık kalacaktır.
Örnek uygulamayı aşağıdaki
komutu kullanarak derleyebilirsiniz.
C:>csc /r:System.dll,System.Data.dll SqlConnectionOrnegi.cs |
Ve
uygulamayı çalıştıralım:
Görüldüğü gibi bir SQL
Server veritabanına bağlantıyı kolayca kurabiliyoruz. Burada belki de üzerinde
durulması yerinde olacak bir konu var: Bağlantı cümlesinin yeri. Yazdığımız
örnekte bağlantı cümlesini hiç bir kaygı duymadan kodumuzun içine gömdük.
Bağlantı cümlesinde yapılacak bir değişiklik için (örneğin SQL Server''in
adresinin değişmesi durumunda) uygulamayı yeniden derleme ihtiyacı doğacağı
açıktır. Bağlantı cümlesini uygulamadan ayrı bir noktada tutmak hem merkezi bir
yönetim hem de esneklik sağlayacak. Elbette bunun düz metin dosyası olması, bir
güvenlik sıkıntısı da doğuracak. Ancak ASP.NET uygulamalarının yapılandırma
dosyaları class=CodeInText>web.config, bu tür kayıtlar için çok ideal bir yer.
Çünkü bu yapılandırma dosyaları düz yazı dosyaları olmalarına rağmen ASP.NET
motoru tarafından ziyaretçilere sunulmuyor. Tıpkı class=CodeInText>.ascx uzantılı dosyalar gibi. Bağlantı cümlesinin
ulaşılabilir olması, dosya özellikle SQL Server login bilgisi içeriyorsa çok
riskli olacaktır.
OleDbConnection
class=CodeInText>OleDbConnection nesnesi, class=CodeInText>System.Data.OleDb aduzayına bağlı, OLE DB .NET verisağlayıcısı üzerinden bir veri kaynağına bağlantı tesis etmemizi sağlar.
Kullanımı aynen yukarıda bahsettiğimiz class=CodeInText>SqlConnection nesnesi gibidir. O nedenle aynı şeyleri
tekrar etmeyeceğiz. Yalnız bu tip bağlantıda, bağlantı cümlesini oluştururken,
hedef veri kaynağına uygun bir Provider seçmemiz gerekecektir. OLE DB
veri sağlayıcısını kullanarak, sistemde OLE DB sağlayıcısı bulunan her veri
kaynağına (SQL Server, Oracle, Access, Indexing Service) bağlanabiliriz.
Biz bir Access veritabanına bağlantı örneği verelim:
| OleDbConnection.cs | |
class=cs_k>using System; using System.Data.OleDb; namespace Evcil.NET { public class COleDb { public class=cs_k>static void Main() { string sBagCumle = @ class=cs_s>"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:data.mdb "; OleDbConnection oConn = new OleDbConnection(sBagCumle); class=cs_k>try { oConn.Open(); } class=cs_k>catch ( OleDbException e ) { Console.WriteLine( e.Message ); } class=cs_k>finally { oConn.Close(); } } } } | |
Yaptığımız
her şeyin class=CodeInText>SqlConnection''la birebir aynı olduğunu görüyorsunuz.
Namespace olarak class=CodeInText>System.Data.OleDb kullandığımıza dikkat edin. Bir kaç
nokta daha var. Bağlantı cümlesinde bir Access veritabanının fiziksel yolunu
belirtiyoruz. Peki string ifadenin önündeki " class=CodeInText>@" simgesi de ne işe yarıyor? Biliyorsunuz ki, C''de " class=CodeInText>" (escape) karakterinin kendinden sonra gelen
ilk karakterle beraber özel görevleri var. Bir fiziksel yol yazarken normal " class=CodeInText>" karakterini doğru olarak ifade etmek için iki adet " class=CodeInText>" yazmamız gerekecekti: " class=CodeInText>C:\Data.mdb". İşte string ifadenin önündeki " class=CodeInText>@" karakteri, o stringdeki tüm " class=CodeInText>" karakterlerini ayrıcalıklı olmaktan çıkarıyor. Bir
kolaylık olarak sunulmuş bize.
Kodda, bağlantıda herhangi bir istisna
çıktığı durumda, istisnanın yakalanması ve her hâlukarda bağlantının kapatılması
için class=CodeInText>try/catch/finally yapısının kullanımını da örneklemiş
olduk.
Bitirirken...
Bu
yazıda, veri kaynağı ile sağlayıcı üzerinden nasıl ilişki kurabileceğimizi
gördük. Bu veri tabanı operasyonları için ilk adımdı. Bundan sonra atacağımız
tüm adımlar, kurduğumuz bu ilişki üzerinden yürüyecek.
İyi çalışmalar.
.NET’te Veri Erişimi : ADO.NET
Her şey gibi ADO da büyük evrimden (veya hafif devrimden)
nasibini aldı. DAO ve ADO derken şimdi ADO.NET''le yüzyüzeyiz.
Microsoft''un veri erişimi için sunduğu yeni ara katman olan ADO.NET, bir çok
heyecan verici yenilikle geliyor. Yazımızda ADO.NET''i ve getirilerini aktarmaya
çalışacağız.
ASP veya VB ile uğraşanlar ADO''yu çok iyi biliyorlar.
.NET''e kadar, veritabanlarına, veri yığınlarına erişim için uygulama
geliştiricilerin kullandığı en yeni ara katman ADO (ActiveX Data Objects)
idi. ADO, gerçekten işleri çok basitleştirmişti. Her türlü veritabanı erişimi
için aynı nesne setini kullanmak, veritabanı ile ilgili detayın sadece bir
bağlantı cümlesine hapsedilmesi ADO''nun çarpıcı özellikleriydi. ADO, Windows
bünyesine yüklenen bir COM bileşeni idi. Gayet anlaşılır nesne modeli ile bizi
OLEDB sağlayıcıları ve ODBC sürücülerinin daha karmaşık olan
modelinden uzak tutarak, kolayca veritabanı operasyonları yapmamızı mümkün
kılıyordu.
Artık karşımızda yepyeni bir veri erişim servisi var:
ADO.NET. ADO.NET, sonuna eklenen "nokta net" ten gayet iyi
anlaşılacağı gibi .NET bünyesinde bir teknoloji. Yani .NET uygulaması geliştiren
bir programcının veriye erişmek için kullandığı her şey ADO.NET''in parçası
olacak. ADO.NET, Framework sınıf kütüphanesinde çeşitli aduzaylarından ve
bunlara bağlı düzinelerce sınıftan oluşan bir alt set.
ADO.NET elbette
ki ADO''nun kullanımında yaşanan güçlüklere çözüm getiriyor ve bunun yanında eski
nesne modelini de kısmen koruyor. Kısaca bakalım:
* ADO.NET,
veriyi XML ile içiçe bir yapıda ifade ediyor. Bu yeni yapının adı
DataSet. Bir dataset standart XML formatında ifade edilebiliyor. Tersi de
aynı derecede kolay bir işlem. ADO''da XML desteği kısıtlı düzeydeydi.
*
ADO ile genelde veri operasyonları aktif bir bağlantı üzerinden gerçekleşirdi.
Şimdi ADO.NET bağlantısız operasyonlara tam destek veriyor. Verilerle
işinizi, veri kaynağına en az seviyede erişerek halledebiliyorsunuz. Bu
kabiliyet, yine DataSet nesnesi üzerinde. Tüm bunlar ADO.NET''in kalbinin DataSet
nesnesi olduğunu anlatmaya yetiyor.
* ADO da veritabanı bağlantıları
OLEDB sağlayıcıları üzerinden gerçekleşiyordu. Bir Access veritabanına bağlanmak
da, bir SQL Server veritabanına bağlanmak da aynı köprüden geçmemizi
gerektiriyordu. Şimdi ADO.NET, SQL Server''le direk konuşabilen bir nesne
topluluğuna sahip. OLEDB ile klasik bağlantı şansınız devam ederken, size
iyilenmiş bir SQL Server erişimi de sunuluyor.
Veri sağlayıcıları biraz
açalım.
Sağlayıcıları
Sağlayıcılar, veri kaynaklarına bağlantı kurar, komut
icra ettirir, onlardan sonuç setleri getirirler. Kısaca veri kaynağı ile
uygulamanız arasında bir köprüdür. (.NET veri sağlayıcılarına, Managed Data
Providers da denilmektedir.)
.NET, bünyesinde iki tane sağlayıcı ile
geliyor: OLEDB .NET Veri Sağlayıcısı ve SQL Server .NET Veri
Sağlayıcısı. İlkinin bildiğimiz OLEDB''nin .NET uyarlaması olduğu belli. Asıl
dikkat çekici olan ikincisi. Bu sağlayıcı Microsoft SQL Server 7 ve üst
sürümleri için optimize edilmiş. Microsoft, SQL Server 7 ve yukarısıyla
çalışacaksanız bu sağlayıcıyı kullanmanızı öneriyor. Zira bu sağlayıcı, SQL
Server ile en alt seviyede, yani TDS (Tabular Data Stream) protokolüyle
konuşuyor. Bu da size performans kazancı olarak dönüyor. Bir sevindirici haber
de geçen haftalarda geldi. Artık Oracle veritabanları için de spesifik
bir .NET sağlayıcısı mevcut.
OLEDB''nin çıkışıyla geri plana çekilen
ODBC (Open Data Base Connectivity) teknolojisinin akıbetini merak edenler
yok mu? Microsoft, ODBC için de bir .NET sağlayıcısı yazdı. Ama bu .NET''in
standart sağlayıcıları arasında gelmiyor. Ayrıca edinmeniz gerekiyor.
(http://msdn.microsoft.com/downloads)
Bilmemiz gereken bir başka önemli
nokta da, her veri sağlayıcısının Framework sınıf kütüphanesinde farklı
aduzayları (namespace) ile temsil ediliyor oluşu. OLEDB sağlayıcısı için class=CodeInText>System.Data.OleDb, SQL Server sağlayıcısı için de class=CodeInText>System.Data.SqlClient aduzayını kullanacağız. ADO.NET
ile ilgili temel sınıfların da class=CodeInText>System.Data aduzayında bulunduğunu hatırlatalım.
Mimarisi
ADO.NET mimarisini ikiye ayırarak incelemek gerekiyor. Biri
bağlantılı, diğeri bağlantısız taraf. Bağlantılı taraf, bir .NET
veri sağlayıcısının üzerinden yapılan bağlantıyla çalışan nesneleri içeriyor. class=CodeInText>Connection, class=CodeInText>Command, class=CodeInText>DataRader, class=CodeInText>DataAdapter bu nesnelerin başlıcaları. Bu nesnelerin
ortak özelliği, aktif bir bağlantıya ihtiyaç duymaları. Diğer tarafta,
bağlantısız bir yapı var:
class=CodeInText>DataSet. DataSet, veri kaynağı bağlantısından bağımsız
olarak tasarlanan bir nesne. Hafızada duran ve istendiğinde XML olarak kalıcı
hale getirilebilen ilişkisel bir veritabanı olarak düşünebilirsiniz. Zira
DataSet, birden fazla tablolar içerebiliyor; bu tablolar arası ilişkiler,
kısıtlamalar, görünümler tanımlamanıza olanak veriyor.
Bu mimariyi en
iyi, dokümantasyondan aldığım aşağıdaki diyagram özetleyecek:
Görüldüğü gibi,
bağlantısız veriyi ifade eden DataSet nesnesi, bağlantılı tarafa DataAdapter
nesnesiyle ulaşıyor. Ve bir DataSet, tek metodla disk üzerinde bir XML
dosyasında saklanabilecek veya bir XML dosyasından vücut bulabilecek esneklikte.
.NET''in XML desteği had safhada olan
veri erişim mimarisine verdiği isim ADO.NET. Bu mimari, Framework sınıf
kütüphanesinde bir çok aduzayı ve düzinelerce sınıfla temsil ediliyor. ADO.NET,
eski versiyonu ADO''dan farklı olarak bağlantısız veri operasyonlarına tam destek
veriyor. Bu iş için DataSet adında iddialı bir nesnesi var.
Bu
yazımızda, ADO.NET''i konsept düzeyinde anlatmaya çalıştık. İlerleyen haftalarda,
tek tek bu mimariyi oluşturan nesneleri, uygulama örnekleriyle beraber
işleyeceğiz.
İyi çalışmalar.
C#, Yeni Bir Soluk
Microsoft ''un Visual Studio.NET paketi ve .NET Framework teknolojisi ile
birlikte sunumunu yaptığı yeni programlama dili C# (Si şarp), çok
bilinmeyenli denklem görünümünden dolayı bu yeni teknolojinin en çok ilgi çeken
kısımlarından birisi oldu. Dile kolay; yepyeni bir programlama dilinden
bahsediyoruz. İsmiyle, sözdizimiyle ve genel yapısıyla C/C++ ''tan türetilmiş
olan C# atalarından daha modern olmakla kalmayıp daha yenilikçi olmayı ihmal
etmiyor. Tamamıyla nesne yönelimli..
C# ile Tanışalım
.NET Framework, programcılara aşina olduğu kod dilini kullanma özgürlüğü tanıyarak bir devrim gerçekleştirdi. Ve, belli belirtimlere sadık kalındığı sürece, farklı dillerle yazılmış uygulamaların birbiriyle etkileşebileceğinin de teminatını verdi. Nasıl mesela? Mesela, A programcısı X diliyle bir Class yazıyor; B programcısı, Y diliyle bu Class'ı devralan (inheritance) yeni bir Class yazıyor. Böylece hangi programcının, hangi dili kullandığı sadece ayrıntı olmaktan öte bir anlam taşımıyor.
Evet, .NET diller arası etkileşime olanak tanıyan, bir çok dile destek veren bir platform. Üçüncü parti derleyiciler yazılarak .NET için her an yeni bir dil daha yazılabilir. Ama herşeyden önce, .NET'in beraberinde sunduğu dillere bakmak gerekiyor. Bu diller 4 tane: C++, Visual Basic .NET, C# ve JScript.NET. Dikkat edilirse bu listede, "ben yeniyim" diye göz kırpan bir tanesi var. Yazımızda, bu yeni dili tanımaya çalışacağız.
Önce okumaya çalışalım. Yeni bir dil olduğu ve de bir sembol içerdiği için telaffuzu konusunda baştan anlaşmak gerekir herhalde. C#'ın resmi okunuşu c-sharp (yani si-şarp). Ancak siz, # sembolü için yörenizde kullanılan karşılığa göre özgün telaffuzlar üretebilirsiniz. si-diyez ve biraz daha milli olan ce-diyez de alternatifler arasında.
C# en basit tanımla, C ve C++ ekolünden türemiş, modern, nesne-yönelimli bir programlama dilidir. .NET Framework hedef alınarak tasarlanmıştır ve komut satırı derleyicisi .NET Framework SDK ile bedava dağıtılmaktadır. C#'ı her türlü .NET uygulamasında kullanabilirsiniz. Bir ASP.NET sayfasında, bir Windows Forms uygulamasında, bir web servisinde veya bir konsol uygulamasında... C#, VB.NET ile beraber .NET iskeletinin iki esas dilini teşkil ediyor. Ve aynı zamanda .NET geliştirileri tarafında en çok ilgi çeken ve tercih edilen dil. Özellikle C# - ASP.NET ikilisinin kullanıldığı Open-Source uygulamalar hızla artmaya başladı.
Komut satırı C# Derleyicisi (csc.exe) hakkında
C# derleyicisi (csc.exe), .cs uzantılı dosyalara kaydedilen C# kaynak-kodlarını IL (Ara Dil - Intermediate Language) koduna çevirerek .dll veya .exe uzantılı assemblyler olarak kaydeder. Bu derleyici, .NET Framework'un 21 mb boyutundaki dokumantasyon ve ek araçlar içermeyen dağıtılabilir kurulumunda da mevcuttur ve bedavadır. .NET Framework kurulumu için http://msdn.microsoft.com/net adresine bakınız.
Sisteminizde .NET Framework kurulu ise, C# komut satırı derleyicisi olan csc.exe yi
%WINDOWS_DIZINI% Microsoft.NET Framework vX.X.XXX
dizini altında bulabilirsiniz. X karakterleri yerine sistemde kurulu framework sürümü gelecektir. Benim sistemim için bu patika şöyle: D:WINNTMicrosoft.NETFrameworkv1.0.3705
Bu dizin altında C# derleyicisinin yanısıra diğer derleyicileri de bulmanız mümkün (vbc.exe, jsc.exe). Bu dizindeki derleyicileri, komut satırında herhangi bir mantıksal noktadan, sadece dosya ismini yazarak kullanarak büyük bir konfor sağlamak istiyorsanız, bu patikayı, sistemin "search path" listesine eklemelisiniz. Aşağıdaki komut yeterli olacaktır:
Set Path=D:WINNTMICROS~1.NETFRAMEW~1V10~1.370;%PATH%
Böylelikle, her noktadan VB.NET, C# ve JS.NET derleyicilerine ulaşabileceksiniz. Yazımızın ilerleyen bölümlerinde bir derleme örneği vereceğiz. O zaman daha iyi anlaşılacaktır.
C#, tasarlanırken C/C++'ın gücü ve Visual Basic'in kolaylığı ve verimliliği birleştirilmiş. Bu dili tasarlayan ekibin başında ise, yine Turbo Pascal ve Borland Delphi gibi efsanelerin yaratımını yönetmiş Anders Hejlsberg var. Kendisi ile C# hususunda yapılmış bir mülakatı okuyabilirsiniz.
C# kaynak-kod dosyalarını .cs uzantılı dosyalarda saklıyoruz. Bir .cs dosyası oluşturmanız için gereken minimum araç sadece bir metin editörü: Not defteri, EditPlus, UltraEdit, vs. Şu gerçeği unutmayalım: tüm .NET uygulamalarını sadece basit metin editörü kullanarak oluşturmak mümkün. Kendinize güveniyorsanız, Visual Studio .NET gibi tasarım harikası bir dosta hiç ihtiyacınız yok.
C#'ın nesne yönelimli bir dil olduğunu söylemiştik. Bu nedenle, her C# kodunda bir class tanımı görmeniz doğaldır. Aşağıda, derlendiğinde kendi başına (stand-alone) bir konsol uygulaması olarak çalışabilecek bir C# kodu var. Kodumuz bir class bünyesinde statik Main() fonksiyonu içeriyor. Fonksiyon içerisinde, konsola yazı gönderilmektedir.
| merhaba.cs | |
|
class IlkProgramIlkHeyecan
{ public static void Main() { System.Console.Write("Merhaba C#"); } } |
|
Bu kodu, merhaba.cs uzantılı bir dosya olarak herhangi bir dizine kaydedin. Eğer, yukarıdaki ara-açıklamada bahsettiğim, derleyici için path ayarlarını yaptıysanız, komut satırında merhaba.cs nin bulunduğu dizine geçip aşağıdaki komutu verirseniz, merhaba.cs'yi başarıyla derleyebileceksiniz.
| Komut satırından derleme komutu | |
|
csc /out:merhaba.exe merhaba.cs
|
|
| Derleyicinin Cevabı | |
|
Microsoft (R) Visual C# .NET Compiler version 7.00.9466
for Microsoft (R) .NET Framework version 1.0.3705 Copyright (C) Microsoft Corporation 2001. All rights reserved. |
|
Bu komut, aynı dizinde merhaba.exe dosyasını üretecektir. Şimdi yine komut satırından aynı dizinde merhaba yazarak bu programı çalıştıralım:

Bu program kodunu aşağıdaki şekilde de yazmak mümkündü:
|
using System;
class IlkProgramIlkHeyecan |
Görüldüğü gibi, C# söz dizimi olarak çok da yeni bir şey getirmiyor. Daha önce C, C++, Java, JavaScript veya PHP gibi dillerle ilgilenmiş olanlar, C# sözdizimine kolaylıkla adapte olacaklar. Bunlar arasında C#'ı, özellikle Java geliştiricileri kendilerine çok yakın bulacaklar. Bu benzerliğin tesadüf olmadığı bir gerçek.
C# dilinin yapısıyla ilgili ayrıntılara sonraki yazılarımızda değineceğiz. Şimdi bir de C#'ı ASP.NET uygulamalası içinde görelim.
| csharp.aspx | |
|
<%@ Page Language="C#" %>
<Script Runat="server"> for ( ; i<3 ; i++) } public class Kisiler public string isim { public string mail { <html> C# ve ASP.NET Buluşması<br><br> <asp:repeater id="rpt" runat="server"> body> |
|
İsim ve Mail şeklinde sadece iki alana sahip bir sınıf tanımı yapıyoruz. Sayfanın
OnLoad olayına yazdığımız fonksiyonda ise, elemanları bu sınıftan oluşan bir dizi tanımlayıp, dizinin elemanlarına değer araması yapıyoruz. Ve HTML alanı içerisinde tanımladığımız
Repeater web kontrolünün
DataSource özelliğine bu diziyi işaret ediyoruz. Repeater'in
DataBind() metodu ile dizideki veriyi listelemiş oluyoruz.
Örneğin çalışır hâli.
C# üstünde çok konuşulacak ve yazılacak bir dil. Popüler, şık ve modern. İnternette C# hakkında sıkı kaynaklar da oluştu (Kaynaklar sayfamıza bakınız). Yükselen değer C#, hem programlamaya yeni başlayanlar için, hem de benzer sözdizimine sahip dillerden gelenler için iyi bir tercih olacaktır.
İyi çalışmalar.