Veysel Uğur KIZMAZ

Entity Framework Many-to-Many Relation

21.09.2011Okunma Sayısı: 16603Kategori: Entity Framework

 Entity Framework’te ilişkilerde one-to-many ve one-to-one ilişkileri duymuştuk. Peki many-to-many ilişkiler entity framework’te nasıl oluşturuluyor? Nasıl kullanılıyor? Many-to-many ilişkiler insert update delete işlemlerinde ne gibi tepkiler veriyor? Bir bardak sıcak çay eşliğinde bu soruları tek tek cevaplayalım.

Veritabanında tablo oluşturulurken iki tablo arasında direk many-to-many ilişki diye bir kavram yoktur. Bir ara tablo sayesinde bu ilişki gerçekleşmektedir. Örneğin veritabanında ürünlerimizi bulundurduğumuz “Urun” tablomuz ve müşterilerimizi bulundurduğumuz “Musteri” tablomuz yer alsın. Müşterinin aldığı ürün kayıtlarını tutabilmek için Urun ile Musteri tabloları arasında hiçbir bağ yoktur. Araya bu iki tabloyu birleştirmek için “MusteriUrun” tablosunu yerleştirirsek bu bilgileri tutabiliriz. O zaman bu tablo yapısını oluşturalım, bakalım nasıl bir yapı olacak 

Entity Framework Many to Many Relation (ilişki) örnek veritabanı
 
 
Projemiz için SQL Server veritabanını kullanıyorum. Ürün ve Müşteri bilgilerinin ortak noktada toplantığı MusteriUrun tablosunda dikkat ederseniz 2 tane primary key yer almaktadır. Bunun sebebi bir müşteri bir üründen sadece 1 tane alabilsin mantığıyla mağazamızın çalışmasıdır (?).
 
Yeni bir Asp.Net Web Application oluşturalım. Oluşturduğumuz uygulamaya “MagazaModel” isminde bir Entity Data Model ekleyelim. Data modelimizde sadece bu üç tabloyu seçelim.
 
Seçim işlemlerini tamamladıktan sonra Bu 3 tablonun veritabanı diyagramında göründüğü gibi (yukarıda göründüğü gibi) görünmesini bekliyoruz. Ben de başta öyle beklemiştim fakat gördüğüm yapı çok farklı ve çok güzel bir ilişkiydi.
 
Entity Framework Many to Many Relation (ilişki) örnek veritabanı
 
 
Entity Framework, Musteri tablomuz ile Urun tablomuz arasında many-to-many (*-*) ilişki kurmuş. İki tablonun Navigation Properties alanına dikkat ederseniz Urun’un altında Musteri, Musteri’nin altında Urun yer almaktadır. Bu da bizi ara tablodan (MusteriUrun) kurtarmaktadır. Yani müşterinin aldığı ürüne musteri.Urun ile, ürünü satın alan müşterilere de urun.Musteri diyerek erişebilmemizi sağlamaktadır.
 
Şimdi bunu bir örnek ile alalım.
 
Veritabanındaki Urun tablomuzun kayıtlarına göz atalım.
 
SQL Server Ürün Tablosu
 
Musteri tablosunun kayıtlarına da göz atalım.
 
SQL Server Müşteri Tablosu
 
MusteriUrun tablosuna da bir bakmakta fayda var 
 
SQL Server Müşteri Ürün tabloları arasındaki ilişki
 
Şimdi Test.aspx sayfamıza şu kodları yazıp 1 ID’li müşterinin (yani benim J) neler aldığını inceleyelim.
 
protected void Getir_MusteriUrunleri(int musteriId)
{
    MagazaEntites entity = new MagazaEntites();
    var musteri = (from m in entity.Musteri
                   where m.MusteriId == musteriId
                   select m).FirstOrDefault();
    string sonuc = "";
    foreach (var urun in musteri.Urun)
    {
        sonuc += urun.Ad + " - " + urun.Marka + " - " + urun.Fiyat + "<br/>";
    }
    Response.Write(sonuc);
}
 
Çalıştırdığımızda ekran çıktısı aşaıdaki gibi olacaktır.
 
Ürün Müşteri tablolarının ekran çıktısı
 
 
 
SELECT işlemi many-to-many relation sayesinde işimzi kolaylaştırıyor. Peki DELETE işleminde nasıl bir tepki alacağız? Örneğin müşterilerin almış olduğu ID’si 1 olan ürünü silmek isteyelim.Bakalım ne tepki alacağız.
 
Öncelikle silme işlemi için standart bir method oluşturalım.
 
protected void Sil_Urun(int urunId)
{
    MagazaEntites entity = new MagazaEntites();
    var silUrun = (from u in entity.Urun
                   where u.UrunId == 6
                   select u).FirstOrDefault();
    entity.DeleteObject(silUrun);
    entity.SaveChanges();
}
 
ID’si 1 olan ürünü silmek istediğimizde bu ürünü satın alan bir müşteri kaydı bulunduğundan silme işlemini GERÇEKLEŞTİRMEYECEKTİR ve aşağıdaki hata ekranını alacağız.
 
Entity framework many to many relation delete error (silme hatası)
 
 
View Detail..->Inner Exception’a baktığımızda hata mesajı olarak şunu demektedir:
 
{"The DELETE statement conflicted with the REFERENCE constraint \"FK_MusteriUrun_Urun\". The conflict occurred in database \"Deneme\", table \"dbo.MusteriUrun\", column 'UrunId'.\r\nThe statement has been terminated."}
 
Buna karşın müşterilerin HİÇBİRİNİN satın ALMADIĞI bir ürünü silmek istediğimizde herhangi bir uyarı vermeden silme işlemini BAŞARIYLA TAMAMLAYACAKTIR.
 
INSERT ve UPDATE işlemini gerçekleştirmek istediğimizde bir tepkiyle karşılaşacak mıyız?
 
Hayır, INSERT ve UPDATE işlemi sırasında mantıklı bir işlem yapıldığı taktirde bir sıkıntı olmamaktadır.
 
 
 
 
Veysel Uğur KIZMAZ
Bilgisayar Mühendisi
veysel@ugurkizmaz.com
www.ugurkizmaz.com