Est-il possible que mon API Web ASP Core garantisse la migration de la base de données vers la dernière migration à l'aide d'EF Core? Je sais que cela peut être fait via la ligne de commande, mais je veux le faire par programme.
Mettre à jour
En me basant sur la réponse de Janshair Khan, j'ai créé cette classe d'assistance:
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using MyWebApi.Models;
namespace MyWebApi
{
public static class DataSeeder
{
public static void SeedData(this IApplicationBuilder app)
{
var context = app.ApplicationServices.GetService<MyContext>();
if (!context.Database.EnsureCreated())
context.Database.Migrate();
}
}
}
Vous pouvez appeler cela depuis la méthode Configure
dans votre Startup.cs
comme ceci:
app.SeedData();
Vous pouvez utiliser
db.Database.EnsureCreated();
pour mettre votre base de données à jour avec votre modèle actuel. Si vous souhaitez activer les migrations (si des migrations ultérieures sont suspectées), utilisez
db.Database.Migrate();
et mettez vos migrations ultérieures dans le temps.
Une note de la documentation sur l'appel à db.Database.EnsureCreated()
:
Notez que cette API n'utilise pas les migrations pour créer la base de données. Dans En outre, la base de données créée ne peut pas être mise à jour ultérieurement à l’aide de migrations. Si vous ciblez une base de données relationnelle et utilisez Pour les migrations, vous pouvez utiliser la méthode DbContext.Database.Migrate () pour assurez-vous que la base de données est créée et que toutes les migrations sont appliquées.
Vous voudrez peut-être simplement appeler db.Database.Migrate()
.
Commentaire tiré de la source trouvée ci-dessus déclaration ici .
Utilisez le code ci-dessous pour exécuter la migration à
public async void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<YourContext`enter code here`>();
context.Database.Migrate();
}
}
Sur la base de la réponse de @steamrolla, je proposerais l'amélioration suivante:
public static class EnsureMigration
{
public static void EnsureMigrationOfContext<T>(this IApplicationBuilder app) where T:DbContext
{
var context = app.ApplicationServices.GetService<T>();
context.Database.Migrate();
}
}
Avec cela, vous pouvez également assurer la migration de différents contextes, par exemple. si vous avez une base de données d'identité.
Usage:
app.EnsureMigrationOfContext<context>();
Je l'ai fait pour migrer par programme avec EF Core 2.1.2 et SQL Server, sur la base des réponses précédentes et réponse de bailando bailando on " Comment et où appeler Database.EnsureCreated et Database.Migrate? ":
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
namespace MyApp
{
public class Startup
{
// ... (only relevant code included) ...
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyAppContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyAppContext")));
// ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
using (var serviceScope = app.ApplicationServices.CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<MyAppContext>();
context.Database.Migrate();
}
// ...
}
}
}
Le projet utilisant ce code est disponible sur Github .
Ceci est une légère correction par rapport à la réponse précédente qui créait une méthode d'extension. Il corrige l'erreur qui est générée telle qu'elle a été écrite.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace MyApp.Extensions
{
public static class IApplicationBuilderExtensions
{
public static void SyncMigrations<T>(this IApplicationBuilder app) where T : DbContext
{
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<DbContext>();
context.Database.Migrate();
}
}
}
}
D'après la réponse de chintan310, voici comment je migre la base de données. Cela garantit la séparation des tâches liées à la base de données en Program.cs
:
public static void Main(string[] args)
{
var Host = BuildWebHost(args);
using (var scope = Host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetService<AppDbContext>();
context.Database.Migrate();
var seeder = scope.ServiceProvider.GetService<AppSeeder>();
seeder.Seed().Wait();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}
Host.Run();
}
private static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();