Asp.net-Core

.NET 6 如何在 program.cs 中自動執行遷移

  • December 8, 2021

在 .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 中做到這一點?

精簡版

聽起來真正的問題是把過去的程式碼放在哪裡Startup.Configure

Program.cs使用中

using (var scope = app.Services.CreateScope())
{
   var db = scope.ServiceProvider.GetRequiredService<SomeDbContext>();
   db.Database.Migrate();
}

比較長的解釋

EF Core Migrations 文件中的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方法中,或者,如果使用 Minimal API,則放在Program.cs. Configuration,ServicesEnvironment可用作WebApplicationBuilder類或由它創建的WebApplication中的屬性。WebApplicationBuilder包含 DI、配置、日誌記錄和主機的建構器介面,例如WebApplicationBuilder.Services暴露IServiceCollection

WebApplication屬性暴露由 配置的中間件WebApplicationBuilder,例如WebApplication.Services暴露IServiceProvider

Minimal API 中的啟動替換

Startup.cs.NET 6中合併了其中的方法Program.cs。 Startup.cs 包含兩種方法:

  • 配置主機和應用程序的方法,例如設置配置和 DI,通過呼叫各種建構器介面IServiceCollection,如IConfigurationBuilder. 這包括以前在Startup.ConfigureServices.
  • 使用主機配置端點、使用服務和中間件的方法。這包括Startup.Configure.

在 .NET 6 中,介面移至 WebApplicationBuilder 和 WebApplication 類。代替 .NET Core 呼叫“神奇”的 Startup 類並註入介面,其中的程式碼Program.cs可以直接訪問它需要的介面。

如果你不需要配置服務,你可以只用 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();

WebApplication一旦通過其Services屬性創建實例,就可以創建 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;
   }
}

引用自:https://stackoverflow.com/questions/70266442