閱讀 Data Annotations - ForeignKey Attribute in EF 6 & EF Core 時發現,Model 怎麼設計會影響定義 FK 方式,該筆記基本就是把 FK 建出來,沒有特別深究優劣
以 [1 對 1] 的 Clothes 和 Status 來說,Clothes model 內有 StatusID Property 和 Status Class 屬性,透過 Data Annotations ForeignKeyAttribute 來進行 FK 設定
建立 Model
Model:Clothes、ClothesDetail 和 Status
FK:
- Clothes - Status:1 對 1
- ClothesDetail - Status:1 對 1
- Clothes - ClothesDetail:1 對多
Mode Code 如下
using System.ComponentModel.DataAnnotations.Schema;
namespace EFCoreMigration.Models
{
public class Clothes
{
public int ClothesID { get; set; }
public string ClothesName { get; set; }
public int StatusID { get; set; }
[ForeignKey("StatusID")]
public Status Status { get; set; }
public ICollection<ClothesDetail> ClothesDetail { get; set; }
}
public class ClothesDetail
{
public int ClothesDetailID { get; set; }
public int ClothesID { get; set; }
public int StatusID { get; set; }
[ForeignKey("StatusID")]
public Status Status { get; set; }
public Clothes Clothes { get; set; }
}
public class Status
{
public int StatusID { get; set; }
public string StatusName { get; set; }
}
}
以 [1 對 1] 的 Clothes 和 Status 來說,Clothes model 內有 StatusID Property 和 Status Class 屬性,透過 Data Annotations ForeignKeyAttribute 來進行 FK 設定
namespace EFCoreMigration.Models
{
public class Clothes
{
public int ClothesID { get; set; }
public string ClothesName { get; set; }
public int StatusID { get; set; }
[ForeignKey("StatusID")]
public Status Status { get; set; }
}
}
以 [1 對多] 的 Clothes 和 ClothesDetail 來說,Clothes model 內有 ICollection 的 ClothesDetail,ClothesDetail model 內有 Clothes Property,透過 Fluent API 來指定 FK
using System.ComponentModel.DataAnnotations.Schema;
namespace EFCoreMigration.Models
{
public class Clothes
{
public int ClothesID { get; set; }
public string ClothesName { get; set; }
public ICollection<ClothesDetail> ClothesDetail { get; set; }
}
public class ClothesDetail
{
public int ClothesDetailID { get; set; }
public int ClothesID { get; set; }
public Clothes Clothes { get; set; }
}
public class MigrationDbContext : DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Clothes>()
.HasMany(c => c.ClothesDetail)
.WithOne(cd => cd.Clothes)
// 關閉 Delete Cascade
.OnDelete(DeleteBehavior.NoAction);
base.OnModelCreating(modelBuilder);
}
}
}
為節省版面,Migration 設定檔案內容就以 ClothesDetail 為主而已,想記錄重點有下述兩點
- migration 時 FK 欄位會自動建立 Index
- Data Annotations 設定的 FK,預設會開啟 Delete Cascade 功能,嘗試透過 Data Annotations 關閉 Delete Cascade,但在 EF Core OnDelete 內提及 Data Annotations 沒有關閉 Delete Cascade 功能,網路上大多也都是透過 Fluent API 來進行關閉
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace EFCoreMigration.Migrations
{
/// <inheritdoc />
public partial class AddFKLab : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ClothesDetail",
columns: table => new
{
ClothesDetailID = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ClothesID = table.Column<int>(type: "int", nullable: false),
StatusID = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ClothesDetail", x => x.ClothesDetailID);
table.ForeignKey(
name: "FK_ClothesDetail_Clothes_ClothesID",
column: x => x.ClothesID,
principalTable: "Clothes",
principalColumn: "ClothesID");
table.ForeignKey(
name: "FK_ClothesDetail_Status_StatusID",
column: x => x.StatusID,
principalTable: "Status",
principalColumn: "StatusID",
// 開啟 Cascade Delete 功能
onDelete: ReferentialAction.Cascade);
});
// 建立 Index
migrationBuilder.CreateIndex(
name: "IX_ClothesDetail_StatusID",
table: "ClothesDetail",
column: "StatusID");
}
}
}
沒有留言:
張貼留言