Sử dụng một cơ sở dữ liệu:
Ở phần trước chúng ta đã cùng nhau xây dựng ứng dụng nhưng chúng đang sử dụng một danh sách công việc giả mạo được viết cứng trong code, ở phần này chúng ta sẽ kết nối chúng với một cơ sở dữ liệu để mọi thứ trở nên hoàn hảo hơn.
Viết mã cơ sở dữ liệu có thể là khó khăn. Trừ khi bạn thực sự biết những gì bạn đang làm, nếu không bạn nên sử dụng các chuỗi truy vấn thô vào ứng dụng của mình. Trình ánh xạ đối tượng quan hệ (ORM) giúp bạn viết mã tương tác với cơ sở dữ liệu dễ dàng hơn bằng cách thêm một lớp trừu tượng giữa mã của bạn với chính cơ sở dữ liệu. Hibernate trong Java và ActiveRecord trong Ruby là hai ORM nổi tiếng.
Có một số ORM cho .NET, một trong số đó được xây dựng bởi Microsoft và được tích hợp sẵn trong Asp.Net Core là Entity FrameWork Core. Entity FrameWork Core giúp dễ dàng kết nối với một số loại cơ sở dữ liệu khác nhau và cho phép bạn sử dụng câu lệnh C# để tạo truy vấn cơ sở dữ liệu và ánh xạ trở lại các model trong C#.
Entity FrameWork Core có thể kết nối tới các cơ sở dữ liệu quan hệ như SQL Server, PostgreSQL, MySQL và cơ sở dữ liệu NOSQL như Mongo. Ở trong những bài tiếp theo chúng ta sẽ sử dụng SQLite để giúp mọi thứ dẽ dàng thiết lập.
Kết nối tới một cơ sở dữ liệu:
Có một số thứ bạn cần để kết nối Entity FrameWork Core tới cơ sở dữ liệu. Ngay khi bạn chạy câu lệnh dotnet new và mô hình MVC + Individual Auth để cài đặt dự án của bạn thì mọi thứ đã được tích hợp sẵn:
Entity Framework Core sử dụng database context và chuỗi kết nối cơ sở dữ liệu để kết nối tới databse. Bạn cần cho Entity Framework core biết context, chuỗi kết nối, nơi cung cấp dữ liệu trong phương thức configureServices của lớp Startup:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(
Configuration.GetConnectionString(“DefaultConnection”)));
Đoạn mã trên thêm ApplicationDbContext vào phân vùng Service và nói cho Entity Framework Core để sử dụng cơ sở dữ liệu SQLite và chuỗi kết nối được cấu hình trong file appsettings.json.
Như bạn có thể thấy, dotnet new tạo ra rất nhiều thứ cho bạn, cơ sở dữ liệu được thiết lập để sẵn sàng sử dụng.Tuy nhiên, nó không có bất kỳ bảng nào để lưu trữ các công việc, bạn cần cập nhật context và di thay đổi cơ sở dữ liệu.
Cập nhật Context:
Thêm một thuộc tính DbSet tới ApplicationDbcontext, bên dưới hàm khởi tạo:
public DbSet<TodoItem> Items { get; set; }
Một DbSet mô tả một bảng, với việc khởi tạo một thuộc tính DbSet<TodoItem>, bạn đang nói với Entity Framework Core rằng bạn muốn lưu trữ các thực thể TodoItem trong một bảng có tên và Items.
Bạn đã cập nhật lớp context, nhưng bây giờ có một vấn đề nhỏ: Context và cơ sở dữ liệu hiện không đồng bộ, vì thực tế không có bảng Items trong cơ sở dữ liệu. Để cập nhật những thay đổi bạn cần tạo một migration.
Khởi tạo một Migration:
Migration theo dõi các thay đổi đối với cơ sở dữ liệu theo thời gian.Chúng có thể hoàn tác lại một tập các thay đổi, hoặc tạo cơ sở dữ liệu thứ hai có cùng cấu trúc như lần đầu tiên. Với các Migration, bạn có một lịch sử sửa đổi đầy đủ như thêm sửa xóa các cột hoặc toàn bộ bảng.
Trong bài trước bạn đã thêm một Items được đặt vào context. Vì bối cảnh hiện tại bao gồm một tập hợp không tồn tại trong cơ sở dữ liệu, bạn cần tạo một migration để cập nhật cơ sở dữ liệu:
dotnet ef migrations add AddItems
Điều này tạo ra một migration mới gọi là AddItem. Nếu bạn mở thư mục Data/migrations bạn sẽ thấy một vài tệp:
Tệp Migration mới của bạn có tiền tố với dấu thời gian khi bạn tạo nó. Nếu bạn mở tệp migration của bạn, bạn sẽ nhìn thấy các phương thức Up, Down:
Data/Migrations/_AddItems.cs
protected override void Up(MigrationBuilder migrationBuilder)
{
// (… some code)
migrationBuilder.CreateTable(
name: “Items”,
columns: table => new
{
Id = table.Column<Guid>(nullable: false),
DueAt = table.Column<DateTimeOffset>(nullable: true),
IsDone = table.Column<bool>(nullable: false),
Title = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey(“PK_Items”, x => x.Id);
});
// (some code…)
}
protected override void Down(MigrationBuilder migrationBuilder)
{
// (… some code)
migrationBuilder.DropTable(
name: “Items”);
// (some code…)
}
Phương thức up chạy khi bạn áp dụng migration vào database. Vì bạn đã thêm Dbset<TodoItem> vào database context, Entity FrameWork Core sẽ tạo bảng Items khi bạn áp dụng migration.Phương thức Down thực hiện ngược lại: nếu bạn cần hoàn tác, bảng Items sẽ được xóa bỏ.
Giải pháp cho các hạn chế SQLite:
Có một số hạn chế của SQLite gây cản trở nếu bạn cố gắng chạy migration nguyên bản. Cho tới khi điều này được khắc phục, hãy giải quyết bằng cách:
Xóa dòng migrationBuilder.AddForeignKey trong phương thức up và dòng migrationBuilder.DropForeignKey trong phương thức down. Nếu bạn sử dụng cơ sở dữ liệu SQL chính thức như SQL Server hoặc MySQL, bạn sẽ không cần phải làm điều này.
Áp dụng migration:
Bước cuối cùng sau khi khởi tạo một migration là thực sự áp dụng nó vào cơ sở dữ liệu:
dotnet ef database update
Câu lệnh sẽ báo cho Entity FrameWork Core tạo bảng Items trong cơ sở dữ liệu.
Mọi thứ gần như đã hoàn thành, trong bài tiếp theo chúng ta sẽ đi khởi tạo một lớp dịch vụ mới cho cơ sở dữ liệu của chúng ta.