.NET 6 如何在 program.cs 中自动运行迁移

Posted

技术标签:

【中文标题】.NET 6 如何在 program.cs 中自动运行迁移【英文标题】:.NET 6 how to run Migration automatically in program.cs 【发布时间】:2021-12-07 20:18:02 【问题描述】:

在.Net 5中,我们过去可以通过将DataContext传递给Configure方法来调用迁移,并在启动类中调用迁移。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext dataContext)

    // migrate any database changes on startup (includes initial db creation)
    dataContext.Database.Migrate();

    ...

我们如何在 .Net 6 中做到这一点?

【问题讨论】:

不确定您在说什么,自 .NET Core 2.0 于 2017 年发布以来,在 Startup 中进行迁移和播种已被弃用。简单的搜索会有所帮助 ***.com/a/45942026/455493。可能有点过时了,方法也略有改动,大体思路是一样的 有什么问题? Applying Migrations at Runtime 表明 dbContext.Database.Migrate() 没有改变。您是在问将以前在 Startup.Configure 中的代码放在哪里? 顺便说一句,感谢您帮助我阐明从 Startup.cs 到我脑海中最小 API 的变化。到目前为止,我主要通过检查哪个类具有我需要的属性来编写正确的代码。这是它第一次真正点击去哪里以及为什么。 【参考方案1】:

短版

听起来真正的问题是把过去存在于 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 中。 ConfigurationServicesEnvironment 等可用作 WebApplicationBuilder 类或由它创建的 WebApplication 中的属性。 WebApplicationBuilder 包含用于 DI、配置、日志记录和主机的构建器接口,例如 WebApplicationBuilder.Services 公开 IServiceCollection

WebApplication属性暴露WebApplicationBuilder配置的中间件,例如WebApplication.Services暴露IServiceProvider

Minimal API 中的启动替换

Startup.cs 中的方法在 .NET 6 中被合并到 Program.cs 中。Startup.cs 包含两种方法:

通过调用IServiceCollectionIConfigurationBuilder等各种构建器接口来配置主机和应用程序的方法,例如设置配置和DI。这包括以前在 Startup.ConfigureServices 中的代码。 使用主机配置端点、使用服务和中间件的方法。这包括 Startup.Configure 中的代码。

在 .NET 6 中,接口移至 WebApplicationBuilder 和 WebApplication 类。 Program.cs 中的代码可以直接访问它需要的接口,而不是 .NET Core 调用“神奇”的 Startup 类并注入接口。

现在可以通过WebApplicationBuilder 类获得主机构建/配置服务。 现在可以通过由 WebApplicationBuilder 构建的 WebApplication 类使用完整的应用程序宿主提供的接口。

如果您不需要配置服务,您可以只用 3 行代码创建一个最小的 API 应用程序:

var app = WebApplication.Create(args);

app.MapGet("/", () => "Hello World!");

app.Run();

在您的情况下,您至少需要配置 DbContext,因此您需要分别使用 WebApplicationBuilderWebApplication。这将在下一节中显示

最小 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;
    

【讨论】:

你就是男人!【参考方案2】:

在 ASP.NET Core 6 中,应该是:

using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<YourDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("YourConnectionString")));
     
var app = builder.Build();
using (var scope = app.Services.CreateScope())

    var db = scope.ServiceProvider.GetRequiredService<YourDbContext>();
    db.Database.Migrate();

【讨论】:

仅代码答案只有在显​​而易见的情况下才可接受。这个不是。如果 OP 知道如何检索其 DbContext 的实例或替换 Startup 方法的方法,则 OP 不会发布问题

以上是关于.NET 6 如何在 program.cs 中自动运行迁移的主要内容,如果未能解决你的问题,请参考以下文章

如何在 .NET 6 最小 API Program.cs 中访问 DbContext

将依赖项传递给 .NET 6 中 program.cs 中的 app.[Methods()]

从 .net 6 的代码覆盖范围中排除 Program.cs [重复]

在 .NET 6 项目中使用 Startup.cs

在 .NET 6 中使用 Startup.cs 更简洁的方法

如何在 .net6 中使用 WebApplicationFactory(没有可说的入口点)