Thành thạo cách cài đặt và cấu hình Entity Framework Core.
Hiểu cách thiết lập mối quan hệ giữa các Model (1-Nhiều, Nhiều-Nhiều).
Sử dụng thành thạo Migration để đồng bộ Database.
Mở dự án ASP.NET Core (Web API hoặc MVC) của bạn. Nhấp chuột phải vào Project --> chọn Manage NuGet Packages... --> chuyển sang tab Browse và cài đặt 3 thư viện sau (chọn phiên bản phù hợp với .NET bạn đang dùng, ví dụ .NET 8 hoặc .NET 10):
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Tạo một thư mục đặt tên là Models. Hãy viết code C# cho các class sau để thể hiện đúng cấu trúc dữ liệu:
MaLoai: Kiểu int, tự tăng (Khóa chính).
TenLoai: Kiểu string, tối đa 50 ký tự, không được để trống (Required).
MoTa: Kiểu string, cho phép Null.
Hinh: Kiểu string, cho phép Null.
Mối quan hệ: Một Loại sẽ có nhiều Hàng Hóa (ICollection<HangHoa>).
MaHH: Kiểu int, tự tăng (Khóa chính).
TenHH: Kiểu string, tối đa 100 ký tự, không được để trống.
Hinh: Kiểu string, cho phép Null.
Gia: Kiểu double hoặc decimal.
Khóa ngoại: Thêm MaLoai (int) làm khóa ngoại và navigation property Loai để liên kết ngược lại class Loai.
💡 Gợi ý code: Sử dụng các Data Annotations như [Key], [Required], [StringLength], [ForeignKey] để định hình thuộc tính trong Database.
Tạo một thư mục tên là Data (hoặc để chung trong Models), tạo class MyDbContext kế thừa từ DbContext.
Tạo hàm khởi tạo (Constructor) nhận vào DbContextOptions<MyDbContext>.
Khai báo các thuộc tính DbSet để EF Core biết cần tạo các bảng nào:
public DbSet<Loai> Loais { get; set; }
public DbSet<HangHoa> HangHoas { get; set; }
(Thực hiện bước này trước để có chuỗi kết nối rồi mới chạy Migration)
Thêm chuỗi kết nối SQL Server vào file cấu hình. Thay đổi Server và Database cho phù hợp với máy của bạn:
{
"ConnectionStrings": {
"DefaultConnection": "Server=YOUR_SERVER_NAME;Database=ShopDbContext;Trusted_Connection=True;TrustServerCertificate=True;"
},
"Logging": { ... }
}
Đăng ký MyDbContext vào container Dependency Injection (DI) của ứng dụng:
using Microsoft.EntityFrameworkCore;
// Thay bằng namespace tương ứng của bạn
using YourProjectName.Data;
var builder = WebApplication.CreateBuilder(args);
// Cấu hình DbContext sử dụng SQL Server
builder.Services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
Mở Package Manager Console (Tools --> NuGet Package Manager -> Package Manager Console) và chạy lần lượt 2 lệnh sau:
Tạo file Migration khởi tạo:
Add-Migration InitDatabase
Cập nhật và tạo Database thực tế dưới SQL Server:
Update-Database
Kiểm tra lại SQL Server Management Studio (SSMS) xem Database ShopDbContext với các bảng Loais và HangHoas đã xuất hiện chưa.
Khám phá tạo mới Controller with Views using Entity Framework cho Loai, HangHoa. Quan sát code được sinh ra và chạy thử.
Bây giờ cửa hàng cần quản lý thêm việc mua hàng. Hãy mở rộng hệ thống bằng cách thực hiện các yêu cầu sau:
Class KhachHang:
MaKH (string, khóa chính, ví dụ: KH001).
HoTen (string, không được trống).
Email (string).
Class HoaDon:
MaHD (int, tự tăng, khóa chính).
NgayDat (DateTime).
DiaChiGiaoHang (string).
Khóa ngoại MaKH liên kết tới bảng KhachHang.
Một Hóa Đơn có thể có nhiều Hàng Hóa, một Hàng Hóa có thể nằm trong nhiều Hóa Đơn.
Yêu cầu: Tạo thêm class trung gian đặt tên là ChiTietHoaDon gồm các thuộc tính: MaHD, MaHH, SoLuong (int), DonGia (double). Định nghĩa Khóa chính phức hợp (Composite Key) gồm cả MaHD và MaHH bằng cách cấu hình OnModelCreating trong file MyDbContext.
Thêm các DbSet cho KhachHang, HoaDon, và ChiTietHoaDon.
Chạy lệnh trong Package Manager Console để cập nhật cơ sở dữ liệu mà không làm mất dữ liệu cũ:
Add-Migration AddCustomerAndOrder
Update-Database
BỔ SUNG 1: Cấu hình ChiTietHoaDon bằng Fluent API (Bổ sung cho Bước 6)
Vì bảng ChiTietHoaDon là bảng trung gian có Khóa chính phức hợp (gồm cả MaHD và MaHH), dùng Data Annotations ([Key]) thông thường sẽ không thiết lập được. Bạn cần bổ sung cấu hình Fluent API trong lớp MyDbContext.
Yêu cầu: Mở file MyDbContext.cs và ghi đè (override) phương thức OnModelCreating:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 1. Cấu hình Khóa chính phức hợp cho ChiTietHoaDon
modelBuilder.Entity<ChiTietHoaDon>()
.HasKey(ct => new { ct.MaHD, ct.MaHH });
// 2. Cấu hình mối quan hệ 1-Nhiều giữa HoaDon và ChiTietHoaDon
modelBuilder.Entity<ChiTietHoaDon>()
.HasOne(ct => ct.HoaDon)
.WithMany(hd => hd.ChiTietHoaDons)
.HasForeignKey(ct => ct.MaHD);
// 3. Cấu hình mối quan hệ 1-Nhiều giữa HangHoa và ChiTietHoaDon
modelBuilder.Entity<ChiTietHoaDon>()
.HasOne(ct => ct.HangHoa)
.WithMany(hh => hh.ChiTietHoaDons)
.HasForeignKey(ct => ct.MaHH);
}
BỔ SUNG 2: Tự động chèn dữ liệu mẫu (Data Seeding)
Để kiểm tra xem Database có hoạt động đúng không mà không cần nhập tay, hãy cấu hình EF Core tự động chèn một vài dữ liệu mẫu khi chạy lệnh Update-Database.
Yêu cầu: Tiếp tục bổ sung vào cuối hàm OnModelCreating đoạn code sau:
// Seeding dữ liệu cho bảng Loai
modelBuilder.Entity<Loai>().HasData(
new Loai { MaLoai = 1, TenLoai = "Điện thoại", MoTa = "Các dòng smartphone" },
new Loai { MaLoai = 2, TenLoai = "Laptop", MoTa = "Máy tính xách tay" }
);
// Seeding dữ liệu cho bảng HangHoa
modelBuilder.Entity<HangHoa>().HasData(
new HangHoa { MaHH = 1, TenHH = "iPhone 17 Pro", Gia = 25000000, MaLoai = 1 },
new HangHoa { MaHH = 2, TenHH = "MacBook Air M6", Gia = 30000000, MaLoai = 2 }
);
⚠️ Lưu ý: Sau khi thêm code Seeding, bạn phải gõ lệnh Add-Migration SeedData và Update-Database ở Package Manager Console để dữ liệu được nạp vào SQL Server.
Sau khi hoàn thành tất cả các bước, bạn hãy tự thử thách bản thân bằng cách trả lời hoặc thực hiện các câu hỏi sau:
Cascade Delete: Nếu bạn xóa một Loai đang có 10 HangHoa, chuyện gì sẽ xảy ra với 10 hàng hóa đó? Làm thế nào để cấu hình nếu xóa Loại thì Hàng Hóa không bị xóa mà chỉ bị gán MaLoai = null?
Lazy Loading: Thử tìm hiểu và cài đặt thư viện Microsoft.EntityFrameworkCore.Proxies để tự động nạp dữ liệu liên quan mà không cần dùng lệnh .Include().