Migration
Nội dung bài · 5 mục
- 1.Khái niệm
- 2.Ví dụ
- 3.Thử ngay
- 4.Lỗi hay gặp
- 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.DesignProject 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 updateEF 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");
}Upchạy khi áp dụng migration: tạo bảngPRODUCTS, cộtIDlà khoá tự tăng. Đây là bản C# củaCREATE TABLEở khoá SQL:nullable: falselàNOT NULL,Oracle:IdentitylàGENERATED AS IDENTITY.Downchạy khi huỷ migration: xoá bảng đó.- Đây là code do công cụ sinh, chỉ cần đọc hiểu.
partialcho phép class nằm ở nhiều file,protected overrideghi đè method của lớp chaMigration. nullable: falselà 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:5000Sử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 addsinh 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âuBạn thêm property Email vào class Customer. Cần làm gì để database có cột Email?
Method Down trong một migration dùng để làm gì?
Thư mục Migrations có nên commit lên git không?