VieTopik
Tiếng HànTiếng AnhIT
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
ASP.NET Core Web APIDữ liệu với EF Core
Bài 14/19
5 phút

Migration

Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt

Bài trước dừng ở lỗi ORA-00942, bảng chưa tồn tại. Class Product đã có, nhưng database chưa có bảng. Về sau, thêm property Stock thì database cũng phải đổi theo. Migration giữ cho cấu trúc database luôn khớp với class trong code.

Khái niệm

📜 Migration: file C# do EF Core sinh ra, mô tả cách đổi cấu trúc database từ phiên bản trước sang phiên bản mới.

Mỗi lần sửa class ảnh hưởng tới bảng, bạn làm hai bước:

Bước Lệnh Làm gì
1 dotnet ef migrations add Ten so class với lần trước, sinh file migration
2 dotnet ef database update chạy các migration chưa chạy vào database

Ví dụ

Cài công cụ một lần, rồi thêm package cho project:

dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design

Project dùng .NET 9 thì thêm --version 9.* vào cả hai lệnh, như bài EF Core và DbContext.

Tạo migration đầu tiên và áp dụng:

dotnet ef migrations add InitialCreate
dotnet ef database update

EF Core sinh thư mục Migrations, trong đó có file dạng rút gọn như sau:

using Microsoft.EntityFrameworkCore.Migrations;

public partial class InitialCreate : Migration
{
    protected override void Up(MigrationBuilder mb)
    {
        mb.CreateTable("PRODUCTS", t => new
        {
            ID = t.Column<int>(nullable: false)
                .Annotation("Oracle:Identity",
                    "START WITH 1 INCREMENT BY 1"),
            NAME = t.Column<string>(nullable: false),
            PRICE = t.Column<decimal>(nullable: false),
        },
        constraints: t =>
            t.PrimaryKey("PK_PRODUCTS", x => x.ID));
    }

    protected override void Down(MigrationBuilder mb) =>
        mb.DropTable(name: "PRODUCTS");
}
  • Up chạy khi áp dụng migration: tạo bảng PRODUCTS, cột ID là khoá tự tăng. Đây là bản C# của CREATE TABLE ở khoá SQL: nullable: false là NOT NULL, Oracle:Identity là GENERATED AS IDENTITY.
  • Down chạy khi huỷ migration: xoá bảng đó.
  • Đây là code do công cụ sinh, chỉ cần đọc hiểu. partial cho phép class nằm ở nhiều file, protected override ghi đè method của lớp cha Migration.
  • nullable: false là tham số có tên (named argument): ghi tên tham số trước giá trị cho dễ đọc.
  • Migration là code, được commit lên git cùng project. Cả team và server dùng chung một lịch sử thay đổi database.

Thử ngay

Sau khi chạy database update, gọi lại GET /api/products sẽ nhận []. Giờ thêm property vào Product:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public decimal Price { get; set; }
    public int Stock { get; set; }
}

Rồi chạy:

dotnet ef migrations add AddStock
dotnet ef database update

Đoán trước khi chạy: migration AddStock sẽ tạo lại cả bảng PRODUCTS, hay chỉ thêm một cột?

Xem kết quả
// Up của migration AddStock (rút gọn)
using Microsoft.EntityFrameworkCore.Migrations;

public partial class AddStock : Migration
{
    protected override void Up(MigrationBuilder mb) =>
        mb.AddColumn<int>(
            name: "STOCK", table: "PRODUCTS",
            nullable: false, defaultValue: 0);

    protected override void Down(MigrationBuilder mb) =>
        mb.DropColumn(name: "STOCK", table: "PRODUCTS");
}

Chỉ thêm một cột. EF Core so class hiện tại với lần migration trước và chỉ sinh phần khác nhau. Các dòng đã có vẫn giữ nguyên, Stock nhận giá trị mặc định 0.

Lỗi hay gặp

Sửa class mà quên tạo migration. Code vẫn chạy, nhưng truy vấn báo lỗi vì database chưa có cột mới.

ORA-00904: "p"."STOCK": invalid identifier
# SAI — thêm property Stock rồi chạy luôn
dotnet run --urls http://localhost:5000
# ĐÚNG — sinh và áp dụng migration trước khi chạy
dotnet ef migrations add AddStock
dotnet ef database update
dotnet run --urls http://localhost:5000

Sửa file migration đã chạy trên server. Server không chạy lại migration đã chạy, nên phần vừa sửa không bao giờ được áp dụng. Muốn đổi thêm thì tạo migration mới.

Tóm tắt

  • Migration là file C# mô tả cách đổi cấu trúc database.
  • migrations add sinh migration từ phần class thay đổi.
  • database update áp dụng các migration chưa chạy.
  • Migration được commit lên git. Không sửa migration đã chạy, hãy tạo migration mới.

Tự kiểm tra

0/3 câu
Câu 1

Bạn thêm property Email vào class Customer. Cần làm gì để database có cột Email?

Câu 2

Method Down trong một migration dùng để làm gì?

Câu 3

Thư mục Migrations có nên commit lên git không?

EF Core và DbContextTruy vấn với EF Core

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt