短版
听起来真正的问题是把过去存在于 Startup.Configure 中的代码放在哪里。
在Program.cs使用
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<SomeDbContext>();
db.Database.Migrate();
}
相当长的解释
EF Core 迁移文档中的 Applying Migrations at Runtime 部分显示,就 EF Core 而言,没有任何变化。
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<SomeDbContext>();
//Same as the question
db.Database.Migrate();
}
host.Run();
}
听起来真正的问题是把曾经存在于Startup.Configure 中的代码放在哪里。该代码可以放在Main 方法中,或者,如果使用最小API,则放在Program.cs 中。 Configuration、Services、Environment 等可用作 WebApplicationBuilder 类或由它创建的 WebApplication 中的属性。 WebApplicationBuilder 包含用于 DI、配置、日志记录和主机的构建器接口,例如 WebApplicationBuilder.Services 公开 IServiceCollection。
WebApplication属性暴露WebApplicationBuilder配置的中间件,例如WebApplication.Services暴露IServiceProvider
Minimal API 中的启动替换
Startup.cs 中的方法在 .NET 6 中被合并到 Program.cs 中。Startup.cs 包含两种方法:
- 通过调用
IServiceCollection、IConfigurationBuilder等各种构建器接口来配置主机和应用程序的方法,例如设置配置和DI。这包括以前在 Startup.ConfigureServices 中的代码。
- 使用主机配置端点、使用服务和中间件的方法。这包括
Startup.Configure 中的代码。
在 .NET 6 中,接口移至 WebApplicationBuilder 和 WebApplication 类。 Program.cs 中的代码可以直接访问它需要的接口,而不是 .NET Core 调用“神奇”的 Startup 类并注入接口。
如果您不需要配置服务,您可以只用 3 行代码创建一个最小的 API 应用程序:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
在您的情况下,您至少需要配置 DbContext,因此您需要分别使用 WebApplicationBuilder 和 WebApplication。这将在下一节中显示
最小 API 中的迁移
在基本的最小 API Program.cs 中:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
一旦通过Services 属性创建了WebApplication 实例,就可以创建DbContexts:
var builder = WebApplication.CreateBuilder(args);
//Register the DbContexts etc.
...
builder.Services.AddDbContext<SomeDbContext>(....);
var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<SomeDbContext>();
db.Database.Migrate();
}
app.MapGet("/", () => "Hello World!");
app.Run();
当然,最好很多为这样的代码使用单独的方法或类,保持Program.cs干净:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<SomeDbContext>(....);
var app = builder.Build();
ApplyMigrations(app);
app.MapGet("/", () => "Hello World!");
app.Run();
static void ApplyMigrations(WebApplication app)
{
using var scope = app.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SomeDbContext>();
db.Database.Migrate();
}
甚至:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<SomeDbContext>(....);
var app = builder.Build();
app.ApplyMigrations()
.UseCustomLogging()
.DoSomeOtherConfiguration()
...;
app.MapGet("/", () => "Hello World!");
app.Run();
使用 ApplyMigrations 在单独的类中扩展方法:
public static DataExtensions
{
public static WebApplication ApplyMigrations(this WebApplication app)
{
using var scope = app.Services.CreateScope()
var db = scope.ServiceProvider.GetRequiredService<SomeDbContext>();
db.Database.Migrate();
return app;
}
}