Entity Framework Core Many to Many Relationship

  Karantina günlerinden herkese selamlar, evde kendime projeler bulmaya çalışırken, bir siteden denk gelipte ilham aldığım, benimde aklımda bir süredir olan wordpress apileri ile bir proje kodlamaya başladım. Fikir kısaca wordpress api lerini kullanarak hazırda olan sitenizden istediğiniz yazı,kategori gibi özellikleri dışarıdaki bir servis aracılığıyla sunmak.

 Bu apinin sunduğu özellikleri kullanarak frontend framework lerinden biriyle bir blog ayağa kaldırmaktı ama aşama aşama gitmeyi tercih ettim.İlk başta Asp.Net Core MVC ile bu sistemi ayağa kaldırmaya çalıştım. Entity Framework ile bir işimiz olmamasına rağmen modelleri oluşturup, MVC yapısını oluşturmaya çalıştım.

 Peki, bu yazı ihtiyacı nereden ortaya çıktı. Post ve Category arasındaki many to many ilişkiyi kurarken karşılaştığım hatalardan. Scaffolding aracı-nı kullanarak Entitylerime karşılık gelen Viewleri ve Controlleri otomatik olarak oluşturmak isterken karşılaştığım hatalardan dolayı bu yazıyı yaz-mak istedim.

İlk başta tüm Post ve Category adında modeli oluşturdum.

public class Post
{
    public int PostID { get; set; }
    public DateTime Date { get; set; }
    public WpTitle Title { get; set; }
    public WpContent Content { get; set; }
}

public class Category
{
     public int CategoryID { get; set; }
     public int Count { get; set; }
     public string Description { get; set; }
     public string Uri { get; set; }
     public string Name { get; set; }
}

Razor Pages Scaffolding bu yazıda yazdığıma benzer bir şekilde Scaffoling aracılığıyla bu sefer MVC için, Post entity içim MVC Controller with view,using Entity Framework seçeneğinden otomatik olarak kodlarımı oluşturdum.

  Entity Framework Core, many-to-many ilişkisine sahip modelleri direk desteklemiyor. Bunu aşmak için bir ara sınıf yazmanız gerekiyor. Aslında yazının ana noktası burası. Ara sınıfımız aşağıdaki gibi birbiriyle ilişkili tabloların primary key ve base entitysini içeriyor.

public class PostCategory
{
    public int PostID { get; set; }
    public Post Post { get; set; }
    public int CategoryID { get; set; }
    public Category Category { get; set; }
}

Daha sonrasında Post ve Category entitylerimi aşağıdaki gibi güncelledim.

public class Post
{
    public int PostID { get; set; }
    public DateTime Date { get; set; }
    public WpTitle Title { get; set; }
    public WpContent Content { get; set; }
    public ICollection<PostCategory> PostCategories { get; set; }
}

public class Category
{
     public int CategoryID { get; set; }
     public int Count { get; set; }
     public string Description { get; set; }
     public string Uri { get; set; }
     public string Name { get; set; }
     public ICollection<PostCategory> PostCategories { get; set; }
}

Peki bu aşamada çözümü bitirdik mi? Migration komutu ile deneyelim.

Add-Migration PostCategory komutunu çalıştırdığımızda tekrar hata alacağız. Hatamız aşağıda gözükmektedir.

The entity type ‘PostCategory’ requires a primary key to be defined. If you intended to use a keyless entity type call ‘HasNoKey()’

Entity imizin aslında tablomuzun primary key tanımlanması gerektiğini söylüyor.

DbContext sınıfımızı aşağıdaki gib güncellediğimizde migration komutunu tekrar çalıştırdığımızda başarılı olacaktır.

public class BlogContext : DbContext
    {
        public BlogContext(DbContextOptions<BlogContext> options)
            : base(options)
        {
        }
        public DbSet<Post> Post { get; set; }
        public DbSet<Category> Category { get; set; }
        public DbSet<PostCategory> PostCategory { get; set; }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<PostCategory>().HasKey(c => new { c.CategoryID, c.PostID });
        }
    }

 Aslında kulağı tersten tutarak anlatmaya çalıştım 🙂 . Biraz kolaya kaçmak için biraz beyin fırtınası vs . Sonuç olarak korona hepimizi bozdu 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.