C#`ta Veritabanı İşlemleri _ders

advertisement
C#’ta Veritabanı İşlemleri
(Database Operations with C#)
ADO.NET’e Genel Bir Bakış
Microsoft
VS.NET’te
gerçekleştirilmektedir.
veritabanı
işlemleri
ADO.NET
ile
ADO.NET yazılımcının çeşitli veritabanlarıyla ilgili akla gelebilecek
bütün işlemlere müdahale edebilmesi için geliştirilmiş .NET dillerinin hepsiyle
birlikte kullanılabilen ortak bir yapıdır.
Bu yapı içerisinde çeşitli veritabanı işlemlerini gerçekleştirmeye yönelik
pek çok nesne, yöntem ve sınıf mevcuttur.
Bu işlemlere örnek vermek gerekirse; Kayıt ekleme, silme, değiştirme,
arama, her türlü SQL işlemleri, transaction yönetimi, Stored Procedure
kullanımı, ilişki yönetimi vb. gibi.
Veri Tabanında Connection (Bağlantı) Kavramı ve
OleDbConnection Sınıfı
ADO.NET mimarisinde, pek çok sınıfın veri kaynakları ile olan
iletişiminde Connection (Bağlantı) nesnelerini kullanırız. Örneğin, bir veri
kayağındaki tablolara ait verileri, DataSet sınıfından bir nesne örneğine taşımak
istediğimizi düşünelim. Bu dataSet nesnesini dolduracak olan DataAdapter
sınıfına, sahip olduğu sql sorgusunun veya komutunun işleyeceği bir hattı
belirtmemiz gerekir. İşte burada devreye Connection (Bağlantı) nesnelerimiz
girer. Ya da bir Command sınıfı nesnesi yardımıyla veritabanı üzerindeki bir
saklı yordamı (stored procedure) çalıştırmak istediğimizi düşünelim. Bu
durumda komutun çalıştırılabileceği bir hattı veri kaynağımız ile Command
nesnesi arasında sağlamamız gerekir. İşte Connection (Bağlantı) nesnemizi
kullanmamız için bir sebep daha. Verdiğimiz bu basit örneklerdende anlaşıldığı
gibi, Connection(bağlantı) sınıfları, veri kaynağına bir hat çekerek, ADO.NET
nesnelerinin bu hat yardımıyla işlemlerini gerçekleştirmelerine imkan sağlarlar.
OleDbConnection baglanti=new OleDbConnection();
/* OleDbConnection nesnemiz oluşturuluyor. */
OleDbConnection sınıfı ile, bir OleDb Data Provider (veri sağlayıcısı)
üzerinden, oledb destekli veri kaynaklarına erişim sağlayabiliriz. Bunu daha iyi
kavramak için aşağıdaki şekle bakalım.
Şekil 1 Şekil 1. OleDbConnection ile Veri Kaynaklarına Bağlantı
Görüldüğü gibi bir OleDbConnection nesnesi öncelikle bir OleDb Data Provider
(OleDb Veri Sağlayıcısı) ile iletişim kurar. Ardından bu veri sağlayıcı istenen
veri kaynağına erişerek, gerekli hattı tesis etmiş olur. Peki bu işlemi nasıl
gerçekleştireceğiz. İşte tüm Connection nesnelerinin en önemli özelliği olan
ConnectionString özelliği bu noktada devreye girmektedir. Kısaca
ConnectionString özelliği ile, veri kaynağı ile sağlanacak olan iletişim hattının
kurulum bilgileri belirlenir.
ConnectionString özelliği, bir takım anahtar-değer çiftlerinin noktalı virgül ile
ayırlmasından oluşturulan string bir bilgi topluluğudur. ConnectionString
özelliği içinde kullanabileceğimiz bu anahtar-değer çiftlerinin en önemlisi
Provider anahtarıdır. Bu anahtara vereceğimiz değer, hangi tip oledb veri
sağlayıcısını kullanmak istediğimizi belirtmektedir.
Sql Sunucusundaki veritabanı için bağlantı:
baglanti.ConnectionString="Provider=SQLOLEDB;Data
Source=localhost;Database=veri;Integrated Security=SSPI";
Yukarıdaki kodlarda ConnectionString özelliği belirleniyor. Provider
(Sağlayıcımız) SQLOLEDB. Bu bir sql sunucusuna bağlanmak istediğimizi
belirtir. Data Source anahtarına localhost değerini atayarak, sunucunun yerel
makinede olduğunu belirtiyoruz. Ancak buraya başka bir adreste girilebilir.
Sunucunuz nerede ise oranın adresi. Database ile, bağlantı hattının açılacağı
veritabanını belirliyoruz. Burada sql sunucumuzda yer alan veri isimli
veritabana bağlantı hattı açıyoruz. Son olarak Integrated Security=SSPI anahtardeğer çifti sayesinde Windows Doğrulaması ile sunucuya bağlanabileceğimizi
belirtiyoruz. Yani sql sunucusuna bağlanma yetkisi olan her windows kullanıcısı
bu hattı tesis edebilecek.
Aynı örnekte bu kez belli bir kullanıcı ile bağlanmak istediğimizi düşünelim. Bu
durumda ConnectionString'imizi aşağıdaki şekilde değiştirmemiz gerekir. Bu
durumda User ID ve Password anahtarlarına gerekli kullanıcı değerlerini atarız.
baglanti.ConnectionString="Provider=SQLOLEDB;Data
Source=localhost;Database=veri;User Id=sa;Password=CucP??80.";
Access veritabanı için bağlantı:
OleDbConnection baglanti=new
OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;data
source=c:\\veri.mdb");
OleDbConnection baglanti=new OleDbConnection();
baglanti.ConnectionString="Provider= Microsoft.Jet.OLEDB.4.0;data
source=c:\\veri.mdb";
Access 2007 için:
baglanti.ConnectionString="Provider= Microsoft.ACE.OLEDB.12.0;data
source=c:\\veri.accdb");
Yukarıda Provider olarak bu kez Microsoft.Jet.OLEDB.4.0 'ı seçerek, bir Access
veritabanına bağlanmak istediğimizi bu Ole Db Provider'a bildirmiş olduk. Daha
sonra bu veri sağlayıcı componenti, Data Source anahtarındaki değere bakarak,
ilgili adresteki veritabanına bir hat çekti.
Bağlatı Hattının Kullanıma Açılması ve Kapatılması:
baglanti.Open(); /* Open metodu ile oluşturduğumuz iletişim hattını kullanıma
açıyoruz. */
baglanti.Close();
/*
Close
metodu
ilede
oluşturulan
iletişim
hattını
kapatıyoruz.*/
ADO.NET ile veritabanı işlemleri
ADO.NET ile veritabanı işlemleri temel olarak 2 kısımda incelenebilir;
• Bağlantılı Veritabanı İşlemleri (Connected Database Operations):
Uygulamanın veritabanına sürekli bağlı olduğu yöntemdir. Değişiklikler
veritabanına direkt olarak yansımaktadır. Gerçek zamanlı erişim sağlar. Temel
nesneleri Command ve DataReader nesneleridir.
Bu yöntem eski ADO versiyonunda da kullanılan yöntemdir. Bu metotta
kullanıcı veritabanına bağlantı sağlar ve istediği sorguyu çalıştırır. Sorgu
sonucunda geri döndürülen veriler uygulamanın ihtiyacına göre kullanılır.
Veritabanına açılan bağlantı herhangi bir nedenden dolayı kesilirse kullanıcının
yeni sorgular yapması mümkün değildir. Bu yüzden veri tabanı bağlantısının
mümkün oılduğunca hızlı bir şekilde kullanılması gerekir.
• Bağlantısız Veritabanı İşlemleri (Disconnected Database
Operations):
Uygulama veritabanına sürekli bağlı değildir. İşlemler veritabanının
gerekli tablolarını içeren sanal bir kopyası üzerinde yapılır. Gerektiği zaman bu
veriler veritabanına aktarılır. Bu aktarımlar haricinde işlemler bağlantısız bir
ortamda gerçekleşmektedir.
Bu yöntem ADO.NET ile birlikte kullanılmaya başlanmıştır. ADO.NET
kütüphanesindeki çeşitli sınıflar yardımıyla bir veritabanındaki istenilen
tablodaki kayıtların tamamı istemcinin hafızasına alınır ve veritabanına olan
bağlantı kesilse bile istemci verilerle oynayabilir. Tabi veritabanı bağlantısı
kesildiği anda hafızadaki verileri veritabanına güncellemek mümkün
değildir.(Güncelleme için yeni bir bağlantının açılması gerekir) Bu yöntemle
istemcinin hafızasında, veritabanındaki tabloların resmen bir modeli
oluşturulur. DataSet isimli sınıf ile hafızadaki bu verilere sistematik bir şekilde
erişmek mümkündür. Üstelik hafızadaki bu veriler içinde çeşitli kompleks
işlemler bile yapılabilmektedir. Bu işlemlerden en önemlisi DataSet içindeki
tablolar arasında ilişki kurmak ve gerektiğinde bu ilişkiye dayanarak çeşitli
sorgular yapmaktır.
C#’ta Bağlantılı(Online) Veritabanı İşlemleri
(Connected Database Operations with C#)
Command (Komut) Nesnesi
Command nesnesi, veri kaynaklarına karşı icra edilecek komutları temsil
eden ADO.NET nesnesidir. 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 ile
* 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.
Yürüttüğümüz sorgu (veya stored procedure) sonucu dönen kayıtlara bir
DataReader nesnesiyle ulaşabiliriz.
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.
Örnek kullanım:
OleDbCommand SorguCalistir = new OleDbCommand(sorgu,baglanti);
DataReader Nesnesi
Command nesnesi, veri kaynağına karşı yürütülen ifadeleri temsil ediyor.
Genellikle sorguları, bir veri seti döndürmek amacıyla işletiriz. ADO.NET veri
sağlayıcısı, komutları icra ettiren Command nesnesinin yanında, dönen veri
kümesini temsil edecek bir yapı da gerçeklemek durumundadır. Bu yapı,
DataReader nesnesidir.
DataReader'in başlıca özellikleri:
DataReader sadece veri okumak amacıyla tasarlanmıştır ve çalışması veri
kaynağıyla kurulmuş canlı bağlantıyı gerektirir.
DataReader, verilerin sadece ileri yönde hareket eden akışını temsil eder.
DataReader ile belli bir anda, sadece bir kayda erişebiliriz. Tüm kayıtlara
erişebilmek için, veri akışının sonuna kadar hareket etmeliyiz(örneğin döngü
ile).
DataReader, kullandığı veri kaynağı bağlantısını, kapanana kadar kendisi
için kilitler.
DataReader Nesnesini Oluşturmak
Daha önceden bahsettiğimiz Connection ve Command nesnelerinin
aksine, DataReader nesnesini bir yapılandırıcı (constructor) metodla kendimiz
oluşturamayız. DataReader, Command nesnesinin ExecuteReader() metodu ile
elde edilir. Bu metod, Command nesnesinin ifade ettiği sorguyu işletir ve dönen
kayıtları temsil edecek DataReader nesnesini oluşturur.
Örnek kullanım:
OleDbConnection baglanti = new OleDbConnection();
//Bağlantı nesnesi tanımlandı
string dosyaadi;
string sorgu;
dosyaadi = @"..\..\..\veri.mdb";
baglanti.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=" + dosyaadi;
//Bağlantı parametreleri tanımlandı
baglanti.Open();
//Bağlantı Açıldı
sorgu = string.Format("select * from Satis");
//Sorgu cümlesi tanımlandı
OleDbCommand SorguCalistir = new OleDbCommand(sorgu, baglanti);
//Hazırlanan sorguyu açılan “baglanti” bağlantısı üzerinden çalıştıracak
olan //SoguCalistir nesnesi tanımlandı.
OleDbDataReader SorguSonucu = SorguCalistir.ExecuteReader();
//Tanımlanan SorguCalistir Command nesnesinin ExecuteReader() metodu ile
//geri dönecek DataReader nesnesine bağlanıyor. Veriler henüz alınmadı!!
while (SorguSonucu.Read())
{
listBox1.Items.Add(SorguSonucu[0].ToString());
}
//Sorguya uygun olarak Read() metodu ile DataReader’a alınan verilerden ilk
//sütun bilgileri (örn. SatisKodu) tek tek listBox1’e eklendi. Kaydın var
//olup olmamasına göre true/ false değeri döndürecektir.
//Read()
metodu
her
seferinde
bir
sonraki
kayda
otomatik
olarak
//konumlanacak. Eğer getirecek kayıt kalmamışsa bu metod false değeri
//verecektir; Bu da döngüden çıkmasına sebep olacaktır
baglanti.Close();
//Bağlantı kapatıldı
DataReader sadece tek bir kaydı hafızaya yükler. Daha önce gösterdiği kayıtlar
ve daha sonra göstereceği kayıtlar hakkında en ufak bilgisi yoktur. Bu nedenle,
bu nesnenin, bir veritabanı tablosunu hafızada temsil etmesini bekleyemeyiz.
ADO.NET'in bu tip "offline"(bağlantısız) veri işlemleri için sunduğu DataSet
adında farklı bir nesne vardır. System.Data isim uzayına bağlı DataSet
nesnesine, DataAdapter nesnesi yardımı ile veritabanından kayıt çekeriz.
Aslında DataAdapter nesnesi de kayıtları, kendi içinde DataReader nesnesi
kullanarak almaktadır.
C#’ta Bağlantısız(Offline) Veritabanı İşlemleri
(Disconnected Database Operations with C#)
Dataset:
 Sanal veritabanı da diyebiliriz. Fiziksel veritabanındaki tabloları, satırları,
ilişkileri yapısında barındırabilir.
 Bellekte geçiçi olarak tutulur.
 Tamamen çevrimdışı olarak ve veri sağlayıcı türünden bağımsız olarak
çalışan DataSet, içerisinde tabloları, bu tablolara ilişkin satır ve sütunları,
tabloların birbirleriyle ilişkilerini hafızada saklayan bir araçtır.
DataSet’i daha iyi anlayabilmeniz açısından özelliklerine değinecek olursak;
 Her zaman çevrimdışı olarak çalışır. Veritabanı ile direk bağlantısı
yoktur. Tamamen bağımsız olarak çalışır.
 İçerisinde tabloları, bu tablolara ait satır ve sütunları, tablo
görüntülerini ve ilişkilerini barındırır.
 Hızlıdır, hafızada tutulduğu için veritabanı ve ağ ortamındaki
yavaşlıklar onu direk etkilemez.
 Veritabanı sağlayıcılarından bağımsızdır. Uyumlu DataAdapter
olduğu sürece DataSet’ler bütün veritabanı sağlayıcılarıyla
çalışabilir.
 Direk olarak veritabanı üzerinde işlem yapılmadığı için yapılan
değişikliklerin geri dönüşü kolaydır. Yapılan değişikliklerin kaydını
tutar. (Anahtar Kelime: RowState)
DataAdapter:
 Dataset’le, veritabanının haberleşmesini sağlayan nesnedir.
 DataAdapter nesnesi ise veri sağlayıcı türlerine göre değişiklik
göstermektedir.
Örneğin,
Access
veritabanı
bağlantısı
için
OleDbDataAdapter nesneleri, SQL Server veritabanı bağlantısı için ise
SqlDataAdapter nesneleri kullanılır.
Fakat kullanım şekli ve yapısı hepsinde aynıdır. DataAdapter’ın 2 temel işlevi
vardır
1. Veritabanındaki istenen verileri DataSet’e aktarmak
Veritabanındaki istenen verileri DataSet’e aktarmak için DataAdapter’ın
Fill() metodu kullanılır.
2. DataSet’teki istenen verileri veritabanına aktarmak
DataSet’teki istenen verileri veritabanına aktarmak için ise
DataAdapter’ın Update() metodu çağrılır.
Connection: (Daha Öncede Anlatılmıştı)
 Veritabanına bağlanmak için kullanılan nesne.
 Connection nesnesi, diğer bir ifade ile DataAdapter’ın veritabana
bağlanarak verilere ulaşabilmesi ve veritabanında değişiklik yapabilmesi
için gerekli fiziksel bağlantının açılmasını ve kapanmasını sağlar.
 Connection sınıfı yine DataSet’ten farklı olarak, DataAdapter’taki gibi
veri sağlayıcı türüne bağımlı olarak çalışırlar. Örneğin, Access veritabanı
bağlantısı için OleDbConnection nesnesi, SQL Server veritabanı
bağlantısı için ise SqlConnection nesnesi kullanılır.
Veritabanı:
Verilerin fiziksel olarak tutulduğu asıl veri kaynağı (Access, SQL, Oracle vb. ile
hazırlanmış veritabanı dosyaları).
Aşağıdaki şekle bakarak bağlantı yapısını daha somut bir şekilde kafanızda
canlandırabilirsiniz;
Örnek Kullanım:
OleDbConnection baglanti = new OleDbConnection();
OleDbDataAdapter da;
DataTable dt = new DataTable();
OleDbCommandBuilder cb;
//DataSet ds = new DataSet();
//BindingSource bs = new BindingSource();
string dosyaadi;
string sqlstring;
dosyaadi = @"..\..\..\veri.mdb";
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
dosyaadi;
//baglanti.Open();
//OleDbDataAdapter nesnesi (da) bağlantıyı işlem yapmadan önce açar,
//işlemini bitirdikten sonra kapatır. Bu yüzden bağlantı açamaya ve
//kapamaya gerek yok..
sorgu = string.Format("select * from Satis");
//sqlstring = "select * from Satis";
da = new OleDbDataAdapter(sorgu, baglanti);
//dataGridView1.Rows.Clear();
da.Fill(dt);
dataGridView1.DataSource = dt;
//da.Fill(ds);
//dataGridView1.DataSource = ds.Tables[0];
//bs.DataSource = ds.Tables[0];
//bs.Sort = "Miktar";
//dataGridView1.DataSource = bs;
cb = new OleDbCommandBuilder(da);
/* CommandBuilder nesnemiz , OleDbDataAdapter nesnemiz için oluşturuluyor.
CommandBuilder’a ait new yapılandırıcısı parametre olarak aldığı
OleDbDataAdapter nesnesinin SelectCommand özelliğindeki sql komutuna
bakarak gerekli diğer UpdateCommand,DeleteCommand ve InsertCommand
komutlarını oluşturuyor. */
da.Update(dt);
/*DataTable’daki
veritabanına gönderiliyor. */
değişiklikler
DataRow satir;
satir = dt.NewRow();
satir["SatisKodu"] = textBox1.Text;
satir["Tarih"] = dateTimePicker1.Text;
satir["UrunAdi"] = textBox3.Text.ToString();
satir["Miktar"] = textBox4.Text.ToString();
satir["BirimFiyat"] = textBox5.Text.ToString();
dt.Rows.Add(satir);
da.Update(dt);
Update
metodu
ile,
DataRow satir;
int skodu;
skodu = Convert.ToInt32(textBox1.Text);
satir = dt.Rows[0];
dt.Rows[skodu]["Tarih"] = dateTimePicker1.Text;
dt.Rows[skodu]["UrunAdi"] = textBox3.Text;
dt.Rows[skodu]["Miktar"] = textBox4.Text;
dt.Rows[skodu]["BirimFiyat"] = textBox5.Text;
da.Update(dt);
int skodu;
skodu = Convert.ToInt32(textBox1.Text);
dt.Rows[skodu-1].Delete();
da.Update(dt);
Download