[ASP.NET Core] Entity Framework Core 使用 CodeFirst 示範

Entity Framework Core (EF Core) 是一個開源的ORM (Object-Relational Mapping) 框架,主要就是在 .NET 應用程式中操作資料庫。 在正式開始使用前會需要先建立程式碼對應到資料庫的物件,例如在資料庫中有一個資料表(Table) ,在 C# 程式碼中也會有一個對應的類別(class) ,這樣就可以達到在程式中操作資料庫的目的了。
而在資料庫中建了一次資料表,又要在 C# 程式碼中再建一次實在是太麻煩了,於是就有 Entity Framework Core 就有工具,可以幫忙把資料表和類別相互轉換,而先建立資料表就叫做資料庫優先(DB First),先建立物件再用指令產生資料表就是程式碼優先(CodeFirst)。

筆者比較習慣先建立資料表(因為在資料庫設計階段就習慣直接建立資料表、拉好關聯,也可以直接查看關聯圖很方便),但是專案遇到要修改資料庫結構的部分就很麻煩,要先回去修改資料結構然後再使用 git stash 暫存當前工作,使用 dotnet ef dbcontext scaffold 指令同步程式碼物件,一一檢查完後回復程式碼才能繼續動作。而且只會 DB First 好像也不太行,未來很可能還是有需要使用到 Code First 的時候,於是馬上來練習。

程式碼示範

建立實體(Entity),也就是對應資料表的物件,例如要建立一個 User 資料表:
    
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;


[Table("users")] // 手動指定資料表名稱,可省略
public class User
{
    public User()
    {
        Id = Guid.NewGuid().ToString(); // 自動產生 UUID
    }
    
    [Key] // 定義為主鍵
    [Column("id")] // 手動指定欄位名稱,可省略
    public string Id { get; set; }

    [Required] // 標記為必填欄位
    [Column(TypeName = "nvarchar(200)")] // 手動指定欄位類型,可省略
    [Comment("使用者名稱")] // 資料庫註解 
    public string Name { get; set; }

    [Column(Order = 2)] // 指定欄位順序,可省略 
    public string Email { get; set; } = string.Empty; // 預設值為空

    public ICollection<DepartmentUser> DepartmentUsers { get; set; } // 關聯多個部門
}

    

部門資料表:
    
using System.ComponentModel.DataAnnotations;

namespace WebApplicationEfCodeCodeFirstTest0528.Models;

// 部門
public class Department
{
    [Key] public int Id { get; set; }
    public string Name { get; set; }

    public ICollection<DepartmentUser> DepartmentUsers { get; set; } // 關聯多個使用者
}
    

使用者與部門關聯資料表:
    
using Microsoft.EntityFrameworkCore;


[PrimaryKey(nameof(UserId), nameof(DepartmentId))] // 複合主鍵 (EF Core 7.0 以上)
public class DepartmentUser
{
    public string UserId { get; set; }
    public User User { get; set; } // 關聯到一個使用者

    public int DepartmentId { get; set; }
    public Department Department { get; set; } // 關聯到一個部門
}
    

對應資料表如下:

建立 ApplicationDbContext.cs 檔案,依據資料表增加 DbSet,之後程式碼要對資料表做新增修改刪除查詢都是透過這個類別:
    
using Microsoft.EntityFrameworkCore;
using WebApplicationEfCodeCodeFirstTest0528.Models;


public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public DbSet<User> Users { get; set; }
    public DbSet<Department> Departments { get; set; }
    public DbSet<DepartmentUser> DepartmentUsers { get; set; }
}
    

在 appsettings.json 設定檔中加入資料庫連接字串:
    
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost,1433;Database=mydb;User=sa;Password=!1MssqlPassword;Trusted_Connection=False;TrustServerCertificate=true;"
  }
}
    

Program.cs
    
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString));

var app = builder.Build();
    

遷移(產生)資料庫

只要確保資料庫連線字串是正確的,能夠連線到 SQL Server 即可。除非登入的使用沒有權限,不然資料表包括資料庫都會自動建立。

安裝 ef 指令工具
    
dotnet tool install --global dotnet-ef
    

更新 ef 指令工具:
    
dotnet tool update --global dotnet-ef
    

建立資料庫遷移紀錄,命名為 InitialCreate:
    
dotnet ef migrations add InitialCreate
    

依據資料庫遷移紀錄更新資料庫:
    
dotnet ef database update
    

然後就會在專案中產生以下檔案:
	
Migrations/
`-- 20240528173359_InitialCreate.cs
|-- 20240528173359_InitialCreate.Designer.cs
`-- ApplicationDbContextModelSnapshot.cs
	
這些檔案看起來的確是有些醜,但是這儲存的是資料庫更新紀錄,會將這些資料寫入到資料庫中一個自動產生的 __EFMigrationsHistory 資料表中,之後要更新時就會自動依據最後更新的版本進行更新。

延伸閱讀:
利用 dotnet ef 指令依據資料庫定義產生 Entity Framework Core 資料庫實體定義程式碼(DB First)

參考資料:
Microsoft.Learn - Creating and Configuring a Model
Microsoft.Learn - Getting Started with EF Core
Microsoft.Learn - Tutorial: Get started with EF Core in an ASP.NET MVC web app

留言

張貼留言

如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com