概要
我们在进行ASP.NET Core开发过程中,经常要面对一个问题,就是开发完成后,需要在测试,生产环境搭建同样站点。而数据库的搭建又是站点搭建中最麻烦的一个环节。
本文介绍一种方法,可以直接在站点启动的时候,自动完成数据库的搭建和数据的初始化操作。
代码和实现
在使用EntityFramework开发过程中,根据各种业务需求,我们会进行大量的数据迁移操作。如果在搭建测试和生产站点的时候,重新手工执行这些数据迁移命令,非常麻烦也非常容易出错。
如果数据迁移的命令可以自动执行,则可以节省大量的环境准备实时间。
环境准备
本文所使用的开发环境如下:
ASP.NET CORE 3.1
SQL Server 2012
EntityFramework Core 5.0.8
相关依赖包如下:
Microsoft.EntityFrameworkCore 5.0.8
Microsoft.EntityFrameworkCore.Design 5.0.8
Microsoft.EntityFrameworkCore.SqlServer 5.0.8
数据库自动迁移和初始化的实现
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace BookManagement.Services
{
public static class DatabaseManagementService
{
// Getting the scope of our database context
public static IApplicationBuilder UseMigrationInitialisation(
this IApplicationBuilder app,
IWebHostEnvironment env,
IConfiguration configuration)
{
using (var serviceScope = app.ApplicationServices.CreateScope())
{
using (var context = serviceScope.ServiceProvider.GetService<BookDBContext>()){
var db = context.Database;
db.Migrate();
SeedData(context, env, configuration);
}
}
return app;
}
private static void SeedData(
BookDBContext _context,
IWebHostEnvironment env,
IConfiguration configuration
){
if (env.IsDevelopment())
{
//Do something for DEV
}
else
{
//Do something for Production
}
}
}
}
我们为IApplicationBuilder 定义一个扩展方法UseMigrationInitialisation,用于执行所有的数据库迁移和数据库数据初始化操作。
- 获取当前DbContext实例,依赖注入DbContext实例代码详见附录。
- 获取当前数据库。
- 执行Migrate方法,该方法将项目中Migrations目录下的所有迁移操作,都会执行一遍。
- 执行SeedData方法,初始化数据库中的各种数据。不同的项目该步骤做什么完全不同,所以不再详述具体内容。
- 考虑到可能的需求,本文将DbContext实例,项目的环境变量实例和项目配置的实例,作为参数传入,以适应更复杂的需求。例如开发和生成环境可能会初始化不同的数据。
- 返回IApplicationBuilder对象,保证在Startup.cs中,我们可以像责任链模式那样,链式调用所有需要的IApplicationBuilder对象方法。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app
.UseHttpsRedirection()
.UseRouting()
.UseAuthorization()
.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
})
.UseMigrationInitialisation(env, Configuration);
}
在Startup.cs中调用UseMigrationInitialisation方法。 从而实现在项目启动时候,自动完成数据库的迁移和数据的初始化。
测试
- 我们在项目的数据库连接字符串中,将数据库名称改成一个不存在的库名。
- 执行站点启动命令:
dotnet run
- 站点启动后,数据库被自动创建和初始化。
附录
DbContext实例依赖注入
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services
.AddDbContext<BookDBContext>(options => options
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}