web-dev-qa-db-fra.com

ASP - Core Migrate EF Core SQL DB au démarrage

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();
37
Zeus82

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.

24
Janshair Khan

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 .

29
steamrolla

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();
    }
}
10
chintan310

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>();
4
pisker

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 .

0
Lauri Harpf

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();
            }
        }
    }
}
0
Dblock247

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();
0
Umut Esen