ENTITY FRAMEWORK CORE İLE BİRE BİR İLİŞKİ VE BİRE ÇOK İLİŞKİ NASIL YAPILIR?

Bu dersimizde çok detaylı olmasa da biraz veritabanı ilişki kavramına değinmek istiyorum. İlişkisel veritabanında 3 ilişki mevcuttur, bunlar;

  • Birebir ilişki (one to one)
  • Bire çok ilişki (one to many)
  • Çoka çok ilişki (many to many)

Detaylı ders anlatımı ve kod takibi için video ders:

Şimdi bunu biraz uygulamamız üzerinde anlatayım. Ben daha önce Model altında Kategori model classı oluşturmuştum. ApplicationDbContet classımda bu tabloya ilişkin kısmı comment satırı haline getiriyorum. Models klasörüme yeni bir class ekliyorum, adını KitapDetay veriyorum.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GRSYKitapEvi_Model.Models
{
    public class KitapDetay
    {
        [Key]
        public int KitapDetay_Id { get; set; }

        [Required]
        public int BolumSayisi { get; set; }

        public int KitapSayfasi { get; set; }

        public double Agirlik { get; set; }

        
    }
}

Bu tablom benim Kitap tablosu ile ilişkili olacak, dolayısı ile Kitap classıma geliyorum. Burada yer alan; ForeignKey olarak belirttiğim alanda değişiklikler yapıyorum.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GRSYKitapEvi_Model.Models
{
    [Table("tb_Kitap")]
    public class Kitap
    {
        [Key]         

        public int Kitap_Id { get; set; }

        [Required]
        public string KitapAdi { get; set; }

        [Required]
        public double Fiyat  { get; set; }

        [Required]
        [MaxLength(13)]
        public string ISBN { get; set; }

        [ForeignKey("Kategori")]
        public int KategoriId { get; set; }

        public Kategori Kategori { get; set; }

        [ForeignKey("KitapDetay")]
        public int KitapDetay_Id { get; set; }
        public KitapDetay KitapDetay { get; set; }


    }
}

Buradan KitapDetay model classıma geliyor, burada da Kitap model classımı ekliyorum.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GRSYKitapEvi_Model.Models
{
    public class KitapDetay
    {
        [Key]
        public int KitapDetay_Id { get; set; }

        [Required]
        public int BolumSayisi { get; set; }

        public int KitapSayfasi { get; set; }

        public double Agirlik { get; set; }

        public Kitap Kitap { get; set; }
    }
}

Bu yaptığım değişikliklerin akabinde bir migration oluşturuyorum. Bunun için package manager consol’a geliyorum.

Add-migration EkleBireBirIliskiKitapveKitapDetay diyorum.

using Microsoft.EntityFrameworkCore.Migrations;

namespace GRSYKitapEvi_DataAccess.Migrations
{
    public partial class EkleBirebirIliskiKitapveKitapDetay : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.AddColumn< int>(
                name: "KitapDetay_Id",
                table: "tb_Kitap",
                type: "int",
                nullable: false,
                defaultValue: 0);

            migrationBuilder.CreateTable(
                name: "KitapDetay",
                columns: table => new
                {
                    KitapDetay_Id = table.Column< int>(type: "int", nullable: false)
                        .Annotation("SqlServer:Identity", "1, 1"),
                    BolumSayisi = table.Column< int>(type: "int", nullable: false),
                    KitapSayfasi = table.Column< int>(type: "int", nullable: false),
                    Agirlik = table.Column< double>(type: "float", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_KitapDetay", x => x.KitapDetay_Id);
                });

            migrationBuilder.CreateIndex(
                name: "IX_tb_Kitap_KitapDetay_Id",
                table: "tb_Kitap",
                column: "KitapDetay_Id",
                unique: true);

            migrationBuilder.AddForeignKey(
                name: "FK_tb_Kitap_KitapDetay_KitapDetay_Id",
                table: "tb_Kitap",
                column: "KitapDetay_Id",
                principalTable: "KitapDetay",
                principalColumn: "KitapDetay_Id",
                onDelete: ReferentialAction.Cascade);
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropForeignKey(
                name: "FK_tb_Kitap_KitapDetay_KitapDetay_Id",
                table: "tb_Kitap");

            migrationBuilder.DropTable(
                name: "KitapDetay");

            migrationBuilder.DropIndex(
                name: "IX_tb_Kitap_KitapDetay_Id",
                table: "tb_Kitap");

            migrationBuilder.DropColumn(
                name: "KitapDetay_Id",
                table: "tb_Kitap");
        }
    }
}

Akabinde update-database diyerek , değişikliklerin veritabanı kısmına yansıtılmasını sağlıyorum.

Yani yaptığım  işlem şu aslında Kitap ve KitapDetay tablosu arasında bire bir ilişki kurdum. Yani kitaba ilişkin olarak her bir detay bilgisi, o kitaba özel bir bilgidir. Dolayısı ile burada bire bir ilişki mevcut.

Gelelim bire çok ilişki örneğine. Uygulamamızda Kitap diye bir tablomuz mevcut, bir de YayınEvi diye bir tablo daha mevcut. Burada şöyle düşünün arkadaşlar, bir kitap bir yayınevinden yayınlanacak. (Bazı kitaplar birkaç yayınevinden çıkar ama biz ISBN verdik ya bunu tek bir bağlantı ile düşünelim). Bir kitap bir yayınevinden çıkacak. Ama herhangi bir YayınEvi’nden birden fazla kitap çıkabilir. Dolayısı ile bu ikisi arasında bir bire çok ilişki mevcut.

Burada bire çok ilişki olması sebebi ile YayınEvi tablomdaki YayinEviId bilgisi, Kitap  tablomda YayinEviId bilgisi ile eşleşir.

Peki bunu data annotation ile uygulama tarafında nasıl yapacağız?

İki tabloda model class olarak ekli, dolayısı ile yeni bir tablo eklemiyorum, tablolaıma geliyorum ve kodlarımı düzenliyorum.

Kitap.cs :

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GRSYKitapEvi_Model.Models
{
    [Table("tb_Kitap")]
    public class Kitap
    {
        [Key]         

        public int Kitap_Id { get; set; }

        [Required]
        public string KitapAdi { get; set; }

        [Required]
        public double Fiyat  { get; set; }

        [Required]
        [MaxLength(13)]
        public string ISBN { get; set; }

        [ForeignKey("Kategori")]
        public int KategoriId { get; set; }

        public Kategori Kategori { get; set; }

        [ForeignKey("KitapDetay")]
        public int KitapDetay_Id { get; set; }
        public KitapDetay KitapDetay { get; set; }

        [ForeignKey("YayinEvi")]
        public int YayinEvi_Id { get; set; }
        public YayinEvi YayinEvi { get; set; }


    }
}

YayinEvi.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GRSYKitapEvi_Model.Models
{
    [Table("tb_YayinEvi")]
    public class YayinEvi
    {
        [Key]
        public int YayinEvi_Id { get; set; }

        [Required]
        public string YayinEviAdi { get; set; }

        [Required]
        public string Lokasyon { get; set; }

        public List< Kitap> Kitap { get; set; }

    }
}

Akabinde add-migration EkleBireCokIliskiKitapveYayinevi migration oluşturuyor ve database güncelleyerek ikisi arasında ilişkimizi tanımlamış oluyoruz.

using Microsoft.EntityFrameworkCore.Migrations;

namespace GRSYKitapEvi_DataAccess.Migrations
{
    public partial class EkleBireCokIliskiKitapveYayinevi : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.AddColumn< int>(
                name: "YayinEvi_Id",
                table: "tb_Kitap",
                type: "int",
                nullable: false,
                defaultValue: 0);

            migrationBuilder.CreateIndex(
                name: "IX_tb_Kitap_YayinEvi_Id",
                table: "tb_Kitap",
                column: "YayinEvi_Id");

            migrationBuilder.AddForeignKey(
                name: "FK_tb_Kitap_tb_YayinEvi_YayinEvi_Id",
                table: "tb_Kitap",
                column: "YayinEvi_Id",
                principalTable: "tb_YayinEvi",
                principalColumn: "YayinEvi_Id",
                onDelete: ReferentialAction.Cascade);
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropForeignKey(
                name: "FK_tb_Kitap_tb_YayinEvi_YayinEvi_Id",
                table: "tb_Kitap");

            migrationBuilder.DropIndex(
                name: "IX_tb_Kitap_YayinEvi_Id",
                table: "tb_Kitap");

            migrationBuilder.DropColumn(
                name: "YayinEvi_Id",
                table: "tb_Kitap");
        }
    }
}

Bir sonraki derste görüşmek üzere..

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir