ASP.NET 框架中有提供 Entity Framework
作為跟資料庫溝通用的 ORM 框架,將資料表轉成 POCO 類別,方便開發人員操作資料庫,用物件導向的概念來取代傳統 ADO.NET
的操作方式。在 ASP.NET Core 框架中也有提供 Entity Framework Core
(EF Core) 來延續這個優良的傳統XD
使用 EF Core
的方式大致可分為兩種:
今天會先介紹用 Code First 的方式來操作資料庫。
為了方便說明,我們今天會操作 Sqlite
資料庫。可以參考 Database Providers 找看看官方或第三方提供的資料庫整合介面。開始前要先加入相關的依賴。
Install-Package Microsoft.EntityFrameworkCore -Version 2.1.4
Install-Package Microsoft.EntityFrameworkCore.Sqlite -Version 2.1.4
Install-Package Microsoft.EntityFrameworkCore.Sqlite.Design -Version 1.1.6
dotnet add package Microsoft.EntityFrameworkCore --version 2.1.4
dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 2.1.4
dotnet add package Microsoft.EntityFrameworkCore.Sqlite.Design --version 1.1.6
這邊用最常看到的 Todo 作為範例。先建立資料模型 TodoModel
,在執行 Migration
時這個類別會被轉換成資料表,並利用 System.ComponentModel.DataAnnotations
命名空間中的 annotation 來為屬性(欄位)加上額外條件:
public class TodoModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public DateTime CreatedAt { get; set; }
public bool Completed { get; set; }
}
再建立一個繼承 DbContext
的類別來跟資料庫溝通,並把資料模型作為 DbSet<TEntity>
屬性:
public class IronmanContext : DbContext
{
public IronmanContext(DbContextOptions<IronmanContext> options) : base(options)
{
}
// 這邊的屬性名稱會作為實際的資料表名稱
public DbSet<TodoModel> Todo { get; set; }
}
在設定檔 appsettings.json
中加入資料庫連線字串,指定資料庫來源:
{
"ConnectionStrings": {
"Sqlite": "Data Source=./todo.db"
}
}
並在 Startup.ConfigureServices
中,把 DbContext
加入服務容器中,同時指定連線字串:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<IronmanContext>(optionsBuilder =>
{
optionsBuilder.UseSqlite(_config.GetConnectionString("Sqlite"));
});
}
在 VS2017 中,建議使用 EF Core Tools 來進行移轉。在套件管理主控台中執行以下命令:
Install-Package Microsoft.EntityFrameworkCore.Tools -Version 2.1.4
Add-Migration IronmanMigration
Update-Database
或者在 dotnet CLI 中執行:
dotnet ef migrations add IronmanMigration
dotnet ef database update
執行 Add-Migration
或 dotnet ef migrations add
時,會在專案目錄中的 Migrations 目錄新增三個檔案,其中檔案名稱開頭的是執行移轉時的時間戳記,可以用來排序後方便觀察資料庫的變化。:
20181102143845_IronmanMigration.cs
:Migration 時的主要作業。20181102143845_IronmanMigration.Designer.cs
:Migration Metadata。IronmanContextModelSnapshot.cs
:當前的模型快照,用來判斷下一次執行移轉時要變更的項目。而執行 Update-Database
或 dotnet ef database update
時,會建立資料庫並套用移轉。最後我們就會得到一個 todo.db
的 Sqlite 檔案。
因為我們已經把繼承 DbContext
的物件加到服務容器中了,在應用程式中就可以直接注入來使用:
public class EntityFrameworkController : Controller
{
private readonly IronmanContext _context;
public EntityFrameworkController(IronmanContext context)
{
_context = context;
}
}
public IActionResult Create()
{
_context.Todo.Add(new TodoModel
{
Title = "EF Core Code First",
CreatedAt = DateTime.Now,
Completed = false
});
_context.SaveChanges();
return new EmptyResult();
}
public IActionResult Read()
{
return Json(_context.Todo.ToList());
}
public IActionResult Update()
{
var todo = _context.Todo.First(m => m.Id == 1);
todo.Completed = true;
_context.SaveChanges();
return new EmptyResult();
}
public IActionResult Delete()
{
var todo = _context.Todo.First(m => m.Id == 1);
_context.Remove(todo);
_context.SaveChanges();
return new EmptyResult();
}
可能對程式設計師來說,先建立資料模型是比較直覺的方式。但個人經驗是在稍微有規模的專案中,資料表的設計比較複雜時,會先有 SA 或 SD 設計好資料表,再由 PG 接手開發,這就要採用明天會說明的 Database First
方式了。(但最近看越來越多人採 Code First 方式開發了,可能是我還不習慣吧QQ)