Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Entity Framework – Code First İle Tabloları İlişkilendirme

Merhaba,

Bir önceki Entity Framework İle Code First Yaklaşımı başlıklı yazımda Entity Framework – Code First yaklaşımına giriş yaparak nasıl veritabanı ve tablo oluşturulduğuna ve bu süreçte nelere dikkat edilmesi gerektiğine detaylıca göz atmıştık. Bu yazımızda ise Code First yapısıyla tablolar arasında Foreign Key ilişkisi kurmayı inceleyeceğiz.

Örneklendirmemi bir okul senaryosu üzerine kuracağım. Okul veritabanı oluşturacak, içerisinde öğretmen ve derslere özel tablolar barındıracağım. İşte gerekli yerlerde senaryoyu düzenleyip ekleme çıkarma yaparsak nedenini yazının akışından yakalayacaksınızdır.

Öncelikle öğretmenler ve derslere özel Entity’lerimizi oluşturalım. Bu entityler veritabanımızda tablo görevi görecek sınıflardır.

    class Ogretmen
    {
        public int OgretmenID { get; set; }
        public string Adi { get; set; }
        public string SoyAdi { get; set; }
    }
    class Ders
    {
        public int DersID { get; set; }
        public string DersAdi { get; set; }
    }

Gördüğünüz gibi öğretmen ve ders tablolarımı nitelendiren sınıfları oluşturmuş oldum.

Şimdi bu tablolar arasında ilişkiyi şu mantıkla kuracağız.

Her öğretmenin bir dersi mevcuttur lakin her dersin birden fazla öğretmeni olabilir.

Olaya bu mantık açısından bakınca öğretmenleri aşağıdaki gibi güncellemeliyiz.

    class Ogretmen
    {
        public int OgretmenID { get; set; }
        public string Adi { get; set; }
        public string SoyAdi { get; set; }
        public int DersID { get; set; }
        public virtual Ders Ders { get; set; }
    }

Gördüğünüz gibi her öğretmenin bir dersi mevcut olduğundan dolayı Ders tipinde bir Ders propertysi, int tipinde de DersID propertysi ekledim.
Aynı mantıkla dersleride aşağıdaki gibi güncellemeliyiz.

    class Ders
    {
        public int DersID { get; set; }
        public string DersAdi { get; set; }
        public virtual List<Ogretmen> Ogretmenler { get; set; }
    }

Madem her bir dersin birden fazla öğretmeni olabilir, bir öğretmenler tipinde liste şeklinde property tuttum.

Şimdi bu yaptığım işlemlerle server arasında bağlantıyı oluşturacak Context’timizi yazalım.

    class OkulDbContext : DbContext
    {
        public DbSet<Ogretmen> Ogretmenler { get; set; }
        public DbSet<Ders> Dersler { get; set; }
    }

Ardından veritabanı oluşturması için server bilgilerimizi config dosyasında oluşturalım.

  <connectionStrings>
    <add name="OkulDbContext" connectionString="Server=.;Database=OkulVeriTabani;Trusted_Connection=true;" providerName="System.Data.SqlClient"/>
  </connectionStrings>

Ve son olarak Context sınıfımızdan bir nesne oluşturup, gerekli veritabanı ve tablolarımızı oluşturalım.

    class Program
    {
        static void Main(string[] args)
        {
            OkulDbContext Veri = new OkulDbContext();
            Veri.Database.Create();
        }
    }

SQL Server’ı incelersek eğer,

Entity Framework - Code First İle Tabloları İlişkilendirme

Entity Framework – Code First İle Tabloları İlişkilendirme


Gördüğünüz gibi veritabanı ve tablolarımız oluşturulmuştur. Bunların yanında tabloların arasındaki ilişkide aşikardır.
Diyagramdan da incelemek gerekirse,
Entity Framework - Code First İle Tabloları İlişkilendirme

Entity Framework – Code First İle Tabloları İlişkilendirme


Gördüğünüz gibi tablolar arasında bu şekilde ilişki kurulmaktadır.

Bir sonraki yazımda görüşmek üzere…
İyi çalışmalar dilerim…

Bunlar da hoşunuza gidebilir...

22 Cevaplar

  1. Yasin ilkalp Arabacı dedi ki:

    Merhabalar hocam
    Benim Tablolarımda CreatedUserId ve UpdatedUserId adında iki kolonum var. bunları Users tablosundaki UserId alanlarıyla ilişkilendirmek istiyorum. Kolon isimleri farklı olduğu için database update ederken hata alıyorum.
    Cevabınız için şimdiden Teşekkür ederim.

    • Gençay dedi ki:
      class ATablo
      {
          public string CreatedUserId { get; set; }
          public string UserId { get; set; }
          public Users User { get; set; }
      .
      .
      .
      }
      
      class BTablo
      {
          public string UpdatedUserId { get; set; }
          public string UserId { get; set; }
          public Users User { get; set; }
      .
      .
      .
      }
      
      class Users
      {
          public string UserId { get; set; }
          public virtual List<ATablo> ATablos { get; set; }
          public virtual List<BTablo> BTablos { get; set; }
      .
      .
      .
      }
      

      Bu mantıkta hareket ettiniz mi? Aksi taktirde ilgili sınıfların içeriklerini burada paylaşırsanız yardımcı olabilirim.

  2. Misafir dedi ki:

    Yukarıda yaptığınız classları ben oluşturdum. Ve “datagridview” in source olarak OGRETMENi verdiğimde gridde 4 sütun geliyor. Öğretmenin Adı, soyadı, DersID numarası(bu sütunda sadece rakam var) birde boş olan bir sütun. Oysaki ben Öğretmenin ad,soyaddan sonra DersId değilde DersinAdi gelmesini istiyorum. Ne yapmalıyım. Saygılarımla.

    • Gençay dedi ki:

      Aşağıda olduğu gibi istediğiniz kolonu DataGridView nesnesinden kaldırabilirsiniz.

                  dgv.Columns["DersId"].Visible = false;
      

      Lakin öğretmene özel dersin adını getirebilmeniz için biraz daha yoğun prosedürel çalışmamız gerekecektir.
      Önce DataGridView nesnesindeki her bir satıra döngü aracılığıyla ulaşarak DersId kolonundaki veriyi elde edeceksiniz. Daha sonra derslerde arama yaparak ilgili id ile eşleşen ders nesnesini elde ederek DataGridView’e aşağıdaki gibi bir kolon ekleyecek ve ders adını bu kolona değer olarak atayacaksınız.

                      DataGridViewImageColumn kolon = new DataGridViewImageColumn();
                      kolon.Name = "clnDersAdi";
                      dgv.Columns.Add(kolon);
      

      Uzun lafın kısası bu şekilde çalışmanız işinizi görecektir.
      Kolay gelsin…

  3. Borahan dedi ki:

    Burada mappingleri nasıl ayarlıyoruz. Bu konudada bilgi vermeniz mümkünmü

  4. Mehmet dedi ki:

    Bir alışveriş sitesi kuruyorum. Kullanıcılar ve Urunler var. Kullanıcıların birden fazla ürünü seçmiş olabilir Urunlerde birden fazla kullanıcıya bağlı olabilir bunun için ayrı bir class mı oluşturmalıyım. Sepet adında bir class oluştursam bunu ve diğer class’ları nasıl yazmalıyım.

    • Gençay dedi ki:

      Öncelikle Merhaba Mehmet;

      Yapman gereken mantık çok kolay. Bir tablo oluşturacaksın yani Code First’te çalışacağın için o tabloya karşılık gelen bir sınıf oluşturacaksın.
      O sınıfın tasarımı aşağıdaki gibi olacak.

      KullanıcıID UrunID Adet
      1 150 25
      1 151 35
      1 152 5
      2 150 15
      2 157 5
      3 147 25
      4 161 1

      Tüm değerler temsilidir. Buradaki verilerden hangi kullanıcı hangi ürünleri almış ya da bir başka deyişle hangi ürünler hangi kullanıcılar tarafından alınmış görülebilmektedir.

      Kolay gelsin.
      Sevgiler.

  5. Abdulkadir dedi ki:

    Güzel içerik için teşekkür ederim.

  6. tolga dedi ki:

    Merhaba hocam, bir site kuruyorum. firmalar, firmalara bagli departmanlar ve yine firmalara bagli meslekler var. Meslek ve departmanlar tablolarinin altinda da personeller tablosu var. Ancak surekli hata aliyorum. bu tablolari nasil yapilandirabilirim?

    • Gençay dedi ki:

      Merhaba,

      Bu makale bu sorunuza cevap verebilecek içeriğe sahiptir.
      En iyisi siz hatalarınızı paylaşın. O şekilde yardımcı olmaya çalışayım.

  7. Hakan dedi ki:

    Hocam selamlar. Aramadığım yer kalmadı. Sizin makalelerinize de bayıldım elinize sağlık. Farkını anlayamadığım, aklımı kurcalayan sorum virtual’ı ne zaman ve neden kullanıyoruz?

    Yani sizin örneğinizdeki Öğretmen class’ında public virtual Ders Ders { get; set; } kısmı mevcut ama ben bunu public Ders Ders { get; set; } şeklinde kullandığımda da aynı sonucu alıyorum, bir problem çıkmıyor. Bu virtual tam olarak ne işe yarıyor, hangi şartlarda kullanmalıyız? Performansa bir etkisi var mıdır kullanıp kullanmamanın.

    Teşekkürler

    • Gençay dedi ki:

      Merhaba,

      Sorunuzu çok küçük bir kelamla aydınlatacağım 🙂

      DbSet propertylerinin virtual ile işaretlenmesinin sebebi Lazy Loading‘i kullanabilmek içindir. Başka bir sebebi yok 🙂 Biliyorsunuz ki compiler, virtual ile işaretlenmiş bir member’ın override edilmiş halini mi yoksa base’de ki halini mi çalıştıracağına runtime’da karar verir. İşte detayda bu özellikle lazy loading ilişkilendirilmiştir.

      Kolay gelsin.

      • Hakan dedi ki:

        Valla hoam Allah razı olsun. Yönlendirmeniz ile hem sizin makalenizi hem de internette lazy loading hakkında makaleleri okudum. Açıkcası bunu kullanmanın mantığını bulamadım 🙂 hemen herkes performansı kötü etkiler, ihtiyaç olan olmayan tüm veriyi basar, her seferinde sql’e sorgu gönderir demiş. Özellikle sizin makalenizde bunu kullanmak istesek bile aktif etmemiz, package yüklememiz gerektiğinden bahsetmişsiniz. Yani örnekler, makaleler yazan, sürekli virtual kullananlarda asla böyle birşey görmedim. Lazyloading’i aktif etmeden virtual kullanmışlar hep. Copy paste, bilse de bilmesede herkes makale basıyor demek ki..

        • Gençay dedi ki:

          Evet, lazy loading tam bir performans sömürücü. Genellikle yazarlardaki virtual takıntısına copy paste değilde el alışkanlığı desek daha doğru olacaktır. Nihayetinde zamanında ilk kaynaklardaki sorgusuz sualsiz virtual örneklendirmeleri bu geleneği başlatmışlardır.

          Velhasıl…
          Faydalandıysanız ne mutlu 🙂
          İyi çalışmalar dilerim.

  8. Onur dedi ki:

    hocam merhabalar,
    bi client tablom var. clientId, name, surname gibi düşünün.
    bi clientAddress tablom var. addressId, clientId, address gibi.

    bir müşterinin birden çok adresi olabileceği için, client classına list şeklinde, clientAddress’e de bir adres bir client’a ait olacağı için normal bir şekilde tabloları bağladım.

    merak ettiğim şu;
    örnek veriyorum, ben 1 idli client classını doldurdum, foreach ile icinden dönüyorum, clientAddress kısmına gittiğimde döngünün içinde, clientAddress columunun içnide tekrar dönüp tüm adreslerini alabilir miyim?

    clientAddress tablosu Id’ye göre otomatik mi dolacak? umarım derdimi anlatabilmişimdir. kolay gelsin teşekkürler.

  9. LEVENT dedi ki:

    Hocam Selamlar,

    Yukarıda ilişki kavramını çok güzel anlatmışsınız, emeklerinize sağlık.
    Sizden bir ricam olacak. Yukarıda Öğretmen ve Ders tablolarına insert-update-delete işlemleri yapmak istersek nasıl bir yol izlemeliyiz? Bununla ilgili bir örnek paylaşabilir misiniz rica etsem.

  10. Burak dedi ki:

    Merhaba yapıyı npgsql tarafında oluşturdum fakat şöyle bir sorunum var gelen veri boş dönüyor.

    Claslarım şu şekilde;

       public class Product:IEntity
        {
            public int Id { get; set; }
            public string ProductName { get; set; }
            public int CustomerId { get; set; } 
            public virtual Customer Customer { get; set; }
        }
    
     public class Customer:IEntity
        {
            public int CustomerId { get; set; }
            public string CustomerName { get; set; }
            public virtual List CustomerProducts { get; set; }
        }
    

    DbContext im şu şekilde;

    public class SellerDbContext:DbContext
        {
    
    
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                optionsBuilder.UseNpgsql(@"User ID=postgres;Password=1234;Host=localhost;Port=5432;Database=SellerDatabase;Pooling=true;");
            }
            
            public DbSet Customers { get; set; }
            public DbSet Products { get; set; }
        }
    
  11. Mustafa dedi ki:

    Hocam kütüphane otomasyonu yapıyorum.

        var ara =from x in ktpdbx.Kutuphane select x;
                if (kutuphaneadiaratbx.Text != null)
                {
    
    
    
                    var sorgu = from c in ara
                                join d in ktpdbx.YayinEvleri on c.AdresID equals d.AdresID
                                join f in ktpdbx.Adresler on c.AdresID equals f.ID
                                where c.KutuphaneAdi.Contains(kutuphaneadiaratbx.Text)
                    select( new
                    {
                        KütüphaneID = c.ID,
                        AdresID = c.AdresID,
                        KütüphaneAdı = c.KutuphaneAdi,
                        YayınEviAdı = d.YayinEviAdi,
                        İl = f.Il,
                        İlçe = f.Ilce,
                        Mahalle = f.Mahalle,
                        Cadde = f.Cadde,
                        Sokak = f.Sokak,
                        BinaNo = f.BinaNO,
                        KatNo = f.Kat,
                        PostaKodu = f.PostaKodu
                    });
                   
                    dgw1.DataSource = sorgu.ToList();
                    dgw1.Columns[0].Visible = false;
                    dgw1.Columns[1].Visible = false;
                }
                if(kutuphaneadiaratbx.Text.Length&lt;=0)
                {
                    listele();
                }
    

    kodum bu tek bir değer döndürüyor birden fazla değer döndüren satırları
    listelemiyor.

    atıyorum datagridview de 2 satırda a harfi geçiyor bunu listelemiyor
    tek satırda b harfi var bunu listeliyor ben böyle olsun istemiyorum.Şarta uyan her satırı listelesin

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir