|
DataSet'teki Tablolar Arasında İlişki Kurma(DataRelation) |
|
Gönderiliyor lütfen bekleyin... |
|
|
Bu makalede veritabanı ile bağlantısız bir biçimde çalışmamızı sağlayan DataSet
sınıfının Relations koleksiyonundan bahsedeceğiz.
.NET ile birlikte veriye erişim modelinde büyük ölçüde değişiklikler olmuştur.
Bütün bu değişikliklerin temelinde yatan neden veriye bağlantısız(disconnected)
bir şekilde erişme modelinin gerçekleştirilmesidir. .NET Framework içerisinde
veriye erişmek için sunulan arayüzlerin tamamı ADO.NET kütüphanesi şeklinde
anılmaktadır. ADO.NET ile veriye(veritabanı, XML) erişmek için iki metot kullanılabilir.
1 - Bağlantılı Erişim : 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.
2 - Bağlantısız Erişim : 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. Bu yazının
ana konusu DataSet'teki tablolar arasında nasıl ilişki kurulacağını göstermektir.
Ancak hatırlatma olması açısından DataSet ile yakından ilişkili olan diğer yapılarıda
aktarmakta fayda görüyorum.
DataSet Nesneleri
DataSet nesnesi herhangi bir veri kaynağı ile ilişkilendirilmiş veri kümesini
temsil eder. Bu veri kaynağı bir veritabanı olacağı gibi XML formatlı bir kaynakta
olabilir. Nitekim DataSet nesnesinde tutulan veriler hafızada XML formatında
tutulmaktadır. DataSet içindeki veriler aynen veri tabanında olduğu gibi tablolar
şeklinde saklanır. Yani bir DataSet nesnesi bir yada birden fazla tablo barındırabilir.
DataSet'in yapısındaki tablolar DataTable isimli sınıfla temsil edilir.
Bu da DataSet'in DataTable türünden nesneleri olan bir kolekesiyona sahip olduğunu
gösterir. Bu koleksiyonun adı Tables' dır. Tables koleksiyonun Add()
ve Remove() metotları kullanılarak DataSet'e yeni tablo eklenip çıkarılabilir.
Tables koleksiyonundaki tablolara indeksleyici yardımıyla erişilebilir. İndeksleyincinin
parametresi tablonun ismi olabileceği gibi tablonun DataSet'teki sıra numarası
da olabilir.
Her bir DataTable nesnesinin Rows ve Columns koleksiyonu bulunmaktadır.
Rows koleksiyonu DataTable'daki kayıtların kümesidir. Bu kümedeki her bir kayıt
ise DataRow isimli sınıfla temsil edilir. Bir kayıttaki veriler sütunlara
ayrılmıştır. Bir kayıt birden fazla sütundan oluşmuştur. Dolayısıyla her bir
kaydın ilgili sütununa erişmek için DataRow sınıfındaki indeksleyici kullanılır.
DataTable'da olduğu gibi indeksleyicinin parametresi sütunun adı yada sıra numarası
olabilir.
DataSet nesnesinde veri ile direkt ilişkili olan bu nesnelerin yanı sıra ilişkisel
veri tabanı modelinin gerektirdiği yapıları barındırmak içinde çeşitli sınıflar
vardır. Bu sınıflardan en önemlisi DataRelation ve Constraint
sınıfıdır. İki tür Constraint(kısıt) sınıfı vardır. Bunlar UniqueConstraint
ve ForeignKeyConstraint sınıflarıdır. Constraint sınıfları temel olarak
verinin tablolara yerleştirilme kurallarını belirler. Örneğin UniqueConstraint
tablodaki bir kaydın tekil olmasını sağlarken, ForeignKeyConstraint sınıfı birbirleriyle
ilişkili tablolardan birinde meydana gelen değişikliğin diğerinde nasıl bir
etki yaratacağını belirler. DataTable nesnelerinin Constraints isimli koleksiyonuna
oluşturulan bu Constraint nesneleri aktarılarak kısıtların çalıştırılması sağlanır.
Dikkat edilmesi gereken nokta kısıtların çalışması için DataSet'in EnforceConstraints
özelliğinin true olması gerektiğidir. Diğer bir önemli sınıf ise DataRelation
sınıfıdır. Bu yazıda DataRelation detaylı bir şekilde anlatılacaktır. Bundan
sonraki yazımda ise Constraint sınıfları üzerinde duracağım.
Yukarıda bahsi geçen bütün sınıflar verinin hafızada modellenmesi için gerekli
olan sınıflardır. Bir eksikliğin farkına varmış olmalısınız! Evet, değinmediğim
diğer önemli yapı DataAdapter sınıfıdır. DataAdapter bir DataSet'in yada
DataTable' ın içini doldurmak için veri kaynağı ile bağlantı kurar. Bu işlemi
yapan DataAdapter sınıfının Fill() metodudur. Bu metot parametre olarak bir
DataSet nesnesi alabileceği gibi DataTable nesnesi de olabilir. Eğer paramatre
bir DataSet nesnesi ise DataSet nesnesi içinde yeni bir DataTable nesnesi oluşturulur
ve veriler bu nesneye aktarılır. Veri kaynağına DataAdapter ile erişirken dikkat
etmemiz gereken önemli bir nokta var : Her DataAdapter nesnesi ile ancak bir
DataTable nesnesi oluşturulabilir. Dolayısıyla birden fazla tablo içeren DataSet
nesneleri ile çalışmak için birden fazla DataAdapter nesnesi oluşturmalıyız.
DataSet içinde yapılan değşikliklerin orjinal veri kaynağında güncellenmesi
içinde DataAdapter kullanılır. DataAdapter'in güncellenen verileri düzgün bir
biçimde ele alabilmesi için UpdateCommand, InsertCommand ve DeleteCommand gibi
özelliklerinin belirtilmesi gerekir. Command nesneleri bir SQL dizgesi
ve Connection nesnesi ile kurulur.
DataRelation Sınıf
İlişkisel veritabanı sistemlerinin en öenmli anahtar konusu tablolar arasında
ilişki kurup bu ilişkiyi kullanarak çeşitli sorgular yapmaktır. Tablolar arasındaki
ilişki, bildiğimiz en popüler veritabanı yönetim sistemlerinde görsel bir şekilde
tasarlanabilmektedir. Peki DataSet'teki tablolar arasındaki bu buna benzer bir
ilişkiyi programlama yolu ile bizler nasıl oluşturabiliriz? Bu sorunun cevabını
vermeden önce tablolar arasındaki ilişkinin ne demek olduğuna açıklık getirelim.
SQL Server 2000 ile birlikte otomatik olarak kurulan Northwind veritabanını
ele alalım. Bu veritabanında Customers(Müşteriler) ve Orders(Siparişler) isimli
iki tablo bulunmakta. Bu tabloların ortak özelliği her iki tabloda da aynı veriyi
temsil eden sütunların bulunmasıdır. Bu sayede Orders tablosundaki siparişlerin
hangi müşteriye ait olduğu saptanmaktadır. Tablolar arasındaki bu ilişkiyi sağlayan
sütun CustomerID isimli sütundur. Custmers tablosundaki bir kayda karşılık Orders
tablosunda birden fazla kayıt bulunmasından daha doğal bir durum olamaz. Çünkü
bir müşteri farklı zamanlarda aynı kimlikle birden fazla alışveriş yapmış olabilir.
Eğer DataSet içine ekleyeceğimiz bu iki tablo arasındaki ilişkiyi yine DataSet
içinde barındırabilirsek herhangi bir müşteriye ait toplam alışveriş miktarını
elde etmemiz çok kolay olacaktır. Söz konusu ilişkiyi kurmak için DataRelation
sınfı kullanılır. Peki DataRelation sınıfı nasıl oluşturulur?
Bir DataRelation nesnesinin iki ana üyesi vardır. Bunlar ParantColumn ve ChildColumn'dur.
Yukarıda bahsettiğim Müşteri ve Sipariş ilşikisinde ParentColumn, Customers
tablosundaki CustomerID sütunudur. ChildColumn ise Orders tablosundaki CustomerID
sütunudur. Buna göre bir DataRelation nesnesi aşağıdaki gibi oluşturulabilir.
DataColumn
parent = ds.Tables[0].Columns["CustomerID"];
DataColumn child = ds.Tables[1].Columns["CustomerID"];
DataRelation dr = new DataRelation("Dr1",parent,child);
//İlk parametre ilişkinin adını belirtir.
|
Yukarıda tanımlanan
ilişkinin anlamı şudur : Her bir müşterinin çok sayıda siparişi bulunmaktadır.
Bu ilişkiden faydalanarak her bir Müşteri kaydına ait Child kayıtları elde etmek
mümkündür. Bu kayıtları elde etmek için DataRow sınıfının GetChildRows()
metodu kullanılmaktadır. Aynı şekilde Orders tablosundaki her siparişin hangi
müşteriye ait olduğunu temsil eden Parent Row kaydını yine DataRow sınıfının
GetParentRow() isimli metodu ile elde edebiliriz. Tabi bütün bu metotların
kullanımının geçerli olması için DataSet'in bu ilişkiden haberi olması gerekir.
DataSet nesnesini bu ilişkiden haberdar etmek için oluşturulan bu DataRelation
nesnesi DataSet'in Relations koleksiyonuna aşağıdaki gibi eklenmelidir.
DataSetNesnesi.Relations.Add(dr);
|
Aşağıdaki örnek uygulamada bir DataSet'in farklı iki tablo ile doldurulması
ve bu iki tablo arasındaki ilişkiye dayanarak ne şekilde sorgu yapılabileceği
gösterilmiştir. Bir konsol uygulaması olan örneğimizde konsoldan girilen bir
müşteriye ait siparişlerin tek tek tutarı ve toplam bedeli ekrana yazdırılmaktadır.
Not : Temel DataSet nesnelerinden olan DataColumn, DataRow ve DataTable sınıflarının
kullanımını bildiğiniz varsayıldığı için bu sınıfların kullanımı detaylı bir
şekilde anlatılmamıştır.
using
System;
using System.Data.SqlClient;
using System.Data;
using System.Data.Common;
class
DataRelationOrnek
{
static void
Main(string[] args)
{
string
kaynak="server=algans;uid=sa; pwd=; database=Northwind";
SqlConnection
con = new SqlConnection(kaynak);
SqlDataAdapter
adp1 = new SqlDataAdapter("select *
from Customers",con);
SqlDataAdapter
adp2 = new SqlDataAdapter("select *
from Orders",new SqlConnection(kaynak));
DataSet
ds = new DataSet("ds1");
DataTable
dtnew = new DataTable("Yeni Tablo");
adp1.Fill(ds);
adp2.Fill(dtnew);
ds.Tables.Add(dtnew);
DataColumn
parent = ds.Tables[0].Columns["CustomerID"];
DataColumn
child = ds.Tables[1].Columns["CustomerID"];
DataRelation
dr = new DataRelation("Dr1",parent,child);
ds.Relations.Add(dr);
DataRow[]
childrows = new DataRow[50];
Console.Write("Müsteri
kodu giriniz : ");
string
ad = Console.ReadLine();
for(int
i=0; i
if(ds.Tables[0].Rows[i]["CustomerID"].ToString()
== ad.ToUpper())
childrows
= ds.Tables[0].Rows[i].GetChildRows(dr);
Console.WriteLine("Alisveris
Tutarlari");
double
total = 0;
foreach(DataRow
drs in childrows)
{
Console.WriteLine(drs["Freight"]);
total
= total + Double.Parse(drs["Freight"].ToString());
}
Console.WriteLine("Toplam
: " + total);
}
}
|
Örneği derleyip
çalıştırdığınızda müşteri kimliği olarak "QUICK" girdiğinizde ilgili
müşteriye ati siparişlerin tutarı ekrana yazdırılacaktır.
ADO.NET ile ilgili bir sonraki yazımda Constraint(kısıt) sınıflarından bahsedeceğim.
Makale:
DataSet'teki Tablolar Arasında İlişki Kurma(DataRelation) ADO.NET ve SQL Sefer Algan
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|