Trong bài viết này, mình sẽ hướng dẫn các bạn sử dụng tính năng EF Core migration để quản lý sự thay đổi của model và cập nhật database.
Để tìm hiểu thêm về CodeFirst Migration, bạn tham khảo bài viết: Tìm hiểu về Code First and Migration
Trường hợp bạn sử dụng SQLite thì cài đặt thêm gói: Microsoft.EntityFrameworkCore.Sqlite
Khai báo Student Model
Để sử dụng CLI, bạn cần cài đặt Microsoft.EntityFrameworkCore.Tools.DotNet
Mở file csproj, thêm dòng:
Bạn cần kiểm tra phiên bản mới nhất tại: https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Tools.DotNet
Sau khi cài đặt thành công, bạn mở PowerShell, gõ lệnh:
Đối với Package Manager Console, bạn cần cài đặt: Microsoft.EntityFrameworkCore.Tools
Tốt nhất bạn nên sử dụng command line, vì khi xảy ra lỗi, thông báo lỗi sẽ rõ ràng hơn
VD: Tạo migration từ PMC và từ CLI
Trong CLI, bạn gõ:
Rõ ràng là từ CLI, bạn sẽ biết project còn thiếu thư viện “Microsoft.EntityFrameworkCore.Design” và thông báo lỗi sẽ chi tiết hơn so với PMC
Bạn cài đặt Microsoft.EntityFrameworkCore.Design từ Nuget.
Gõ lại lệnh:
No parameterless constructor was found on 'SchoolContext'. Either add a parameterless constructor to 'SchoolContext' or add an implementation of 'IDbContextFactory<SchoolContext>' in the same assembly as 'SchoolContext'
Khi bạn không truyền parameter vào hàm ctor SchoolContext() hoặc không sử dụng DI, thì lúc này hàm OnConfiguring sẽ được gọi để thiết lập connection string.
Bạn cài đặt packages:
Cập nhật Database: Đối với CLI
Để tìm hiểu thêm về CodeFirst Migration, bạn tham khảo bài viết: Tìm hiểu về Code First and Migration
Khai báo Model
Đầu tiên, bạn cài đặt các package: Microsoft.EntityFrameworkCore.SqlServer:Install-Package Microsoft.EntityFrameworkCore.SqlServer
Trường hợp bạn sử dụng SQLite thì cài đặt thêm gói: Microsoft.EntityFrameworkCore.Sqlite
Khai báo Student Model
public class Student
{
public int Id { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
}
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<Schoolcontext> options)
: base(options)
{ }
public DbSet<student> Students { get; set; }
}
Configuring DbContextOptions
Để tạo đối tượng SchoolContext, bạn cần đối tượng DbContextOptions làm tham số. Hoặc bạn có thể sử dụng hàm OnConfiguring.Cài đặt Migration
Để sử dụng CLI, bạn cần cài đặt Microsoft.EntityFrameworkCore.Tools.DotNet
Mở file csproj, thêm dòng:
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" />
Bạn cần kiểm tra phiên bản mới nhất tại: https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Tools.DotNet
Sau khi cài đặt thành công, bạn mở PowerShell, gõ lệnh:
dotnet ef
Đối với Package Manager Console, bạn cần cài đặt: Microsoft.EntityFrameworkCore.Tools
Tốt nhất bạn nên sử dụng command line, vì khi xảy ra lỗi, thông báo lỗi sẽ rõ ràng hơn
VD: Tạo migration từ PMC và từ CLI
Trong CLI, bạn gõ:
dotnet ef migrations add InitialSchema
Trong PMC, bạn gõ:add-migration InitialSchema
Kết quả từ PowerShell |
Kết quả từ Package Manager Console |
Rõ ràng là từ CLI, bạn sẽ biết project còn thiếu thư viện “Microsoft.EntityFrameworkCore.Design” và thông báo lỗi sẽ chi tiết hơn so với PMC
Bạn cài đặt Microsoft.EntityFrameworkCore.Design từ Nuget.
Gõ lại lệnh:
dotnet ef migrations add InitialSchema
Bạn sẽ gặp 1 lỗi mới:No parameterless constructor was found on 'SchoolContext'. Either add a parameterless constructor to 'SchoolContext' or add an implementation of 'IDbContextFactory<SchoolContext>' in the same assembly as 'SchoolContext'
Khắc phục
Cách 1:
Sử dụng hàm OnConfiguring.Khi bạn không truyền parameter vào hàm ctor SchoolContext() hoặc không sử dụng DI, thì lúc này hàm OnConfiguring sẽ được gọi để thiết lập connection string.
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<Schoolcontext> options)
: base(options)
{ }
public SchoolContext()
{
}
public DbSet<student> Students { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=school.db");
}
}
Cách 2
Sử dụng IDbContextFactorypublic class MyDbContextFactory : IDbContextFactory<schoolcontext>
{
public SchoolContext Create(DbContextFactoryOptions options)
{
var builder = new DbContextOptionsBuilder<schoolcontext>();
builder.UseSqlServer("Server=.;Database=pinchdb;Trusted_Connection=True;MultipleActiveResultSets=true");
return new SchoolContext(builder.Options);
}
}
Trường hợp bạn không thích hard-code, mà lấy connection string từ file appsettings.json:Bạn cài đặt packages:
- Microsoft.Extensions.Configuration
- Microsoft.Extensions.Configuration.FileExtensions
- Microsoft.Extensions.Configuration.Json
public class SchoolContextFactory : IDbContextFactory<SchoolContext>
{
public SchoolContext Create(DbContextFactoryOptions options)
{
return Create(options.ContentRootPath, options.EnvironmentName);
}
public SchoolContext Create()
{
var environmentName = Environment.GetEnvironmentVariable(
"Hosting:Environment");
var basePath = AppContext.BaseDirectory;
return Create(basePath, environmentName);
}
private SchoolContext Create(string basePath, string environmentName)
{
var builder = new ConfigurationBuilder()
.SetBasePath(basePath)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{environmentName}.json", true)
.AddEnvironmentVariables();
var config = builder.Build();
var connstr = config.GetConnectionString("DefaultConnection");
if (String.IsNullOrWhiteSpace(connstr))
{
throw new InvalidOperationException(
"Could not find a connection string named 'DefaultConnection'.");
}
else
{
return Create(connstr);
}
}
private SchoolContext Create(string connectionString)
{
if (string.IsNullOrEmpty(connectionString))
throw new ArgumentException(
$"{nameof(connectionString)} is null or empty.",
nameof(connectionString));
var optionsBuilder =
new DbContextOptionsBuilder<SchoolContext>();
optionsBuilder.UseSqlServer(connectionString);
return new SchoolContext(optionsBuilder.Options);
}
}
Cách 3
Sử dụng IDesignTimeDbContextFactory - Đối với Entity Framework Core 2.0 trở lên
public class MyDbContextFactory : IDesignTimeDbContextFactory<SchoolContext>
{
public SchoolContext CreateDbContext(string[] args)
{
var builder = new DbContextOptionsBuilder<SchoolContext>();
builder.UseSqlServer("Server=.;Database=pinchdb;Trusted_Connection=True;MultipleActiveResultSets=true");
return new SchoolContext(builder.Options);
}
}
Lưu ý: bạn nhớ cài đặt package: Microsoft.Extensions.ConfigurationCập nhật Database: Đối với CLI
dotnet ef database update
Đối với PMC
update database
Revert Migration
[Command line]
dotnet ef database update Create
[Package Manager Console]
update-database Create
Link download: http://www.mediafire.com/file/1ih7o0864pgg5oe/EfCoreMigrationWithFactory.rarTham khảo
- Các lệnh trong .NET Core CLI: https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet
- EF Core Migrations without Hard-coding a Connection String using IDbContextFactory: https://www.benday.com/2017/02/17/ef-core-migrations-without-hard-coding-a-connection-string-using-idbcontextfactory/
Nhận xét
Đăng nhận xét