web-dev-qa-db-fra.com

Comment et où appeler Database.EnsureCreated et Database.Migrate?

J'ai une application ASP.NET MVC 6 et j'ai besoin d'appeler les méthodes Database.EnsureCreated et Database.Migrate.

Mais où devrais-je les appeler?

40
bailando bailando

Je pense que c'est une question importante et qu'il faut y répondre!

Qu'est-ce que Database.EnsureCreated?

context.Database.EnsureCreated() est la nouvelle méthode de base EF qui garantit que la base de données pour le contexte existe. S'il existe, aucune action n'est entreprise. S'il n'existe pas, la base de données et tout son schéma sont créés et garantissent sa compatibilité avec le modèle pour ce contexte.

Remarque: Cette méthode n'utilise pas les migrations pour créer la base de données. 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 des migrations, vous pouvez utiliser la méthode DbContext.Database.Migrate() pour vous assurer que la base de données est créée et que toutes les migrations sont appliquées.

Comment avons-nous fait cela avec EF 6?

context.Database.EnsureCreated() est équivalent aux approches de EF 6 énumérées ci-dessous:

  1. Console du gestionnaire de paquets: 

    Enable-Migrations -EnableAutomaticMigrations. Add-Migration/Update-Database.

  2. À partir du code:

    Database.SetInitializer CreateDatabaseIfNotExists

ou

With DbMigrationsConfiguration et définissez AutomaticMigrationsEnabled = true;

Qu'est-ce que Database.Migrate?

Applique toutes les migrations en attente pour le contexte à la base de données. Va créer la base de données si elle n'existe pas déjà.

Comment avons-nous fait cela avec EF 6?

context.Database.Migrate() est équivalent aux approches de EF 6 énumérées ci-dessous:

  1. Console du gestionnaire de paquets:

    Update-Database -TargetMigration 

  2. Avec une configuration DbMigrationsConfiguration personnalisée: 

    AutomaticMigrationsEnabled = false; ou avec DbMigrator.

Conclusion :

Si vous utilisez des migrations, il y a context.Database.Migrate(). Si vous ne souhaitez pas de migrations et souhaitez simplement une base de données rapide (généralement pour les tests), utilisez context.Database.EnsureCreated ()/EnsureDeleted ().

50
Bassam Alugili

Avant tout, vous devriez lire ceci de Rowan Miller:

... EnsureCreated contourne totalement les migrations et crée simplement le schéma pour vous, vous ne pouvez pas mélanger cela avec les migrations. EnsureCreated est conçu pour les tests ou le prototypage rapide là où vous êtes d'accord déposer et recréer la base de données à chaque fois. Si vous utilisez migrations et souhaitez les appliquer automatiquement au démarrage de l'application, alors vous pouvez utiliser context.Database.Migrate() à la place.

Selon la réponse ici vous devez ajouter Globals.EnsureDatabaseCreated(); le à Startup.cs:

Fonction de démarrage dans Startup.cs:

public Startup(IHostingEnvironment env)
{
    // Set up configuration sources.
    var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddEnvironmentVariables();

    if (env.IsDevelopment())
    {
        // This will Push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
            builder.AddApplicationInsightsSettings(developerMode: true);
    }
    Configuration = builder.Build();
    Globals.Configuration = Configuration;
    Globals.HostingEnvironment = env;
    Globals.EnsureDatabaseCreated();
}

Et définissez Globals.EnsureDatabaseCreated() comme suit:

public static void EnsureDatabaseCreated()
    {
        var optionsBuilder = new DbContextOptionsBuilder();
        if (HostingEnvironment.IsDevelopment()) optionsBuilder.UseSqlServer(Configuration["Data:dev:DataContext"]);
        else if (HostingEnvironment.IsStaging()) optionsBuilder.UseSqlServer(Configuration["Data:staging:DataContext"]);
        else if (HostingEnvironment.IsProduction()) optionsBuilder.UseSqlServer(Configuration["Data:live:DataContext"]);
        var context = new ApplicationContext(optionsBuilder.Options);
        context.Database.EnsureCreated();

        optionsBuilder = new DbContextOptionsBuilder();
        if (HostingEnvironment.IsDevelopment()) optionsBuilder.UseSqlServer(Configuration["Data:dev:TransientContext"]);
        else if (HostingEnvironment.IsStaging()) optionsBuilder.UseSqlServer(Configuration["Data:staging:TransientContext"]);
        else if (HostingEnvironment.IsProduction()) optionsBuilder.UseSqlServer(Configuration["Data:live:TransientContext"]);
        new TransientContext(optionsBuilder.Options).Database.EnsureCreated();
    }

Pour utiliser context.Database.Migrate(), voir ici ou ici .

10
James P

Avec les informations fournies par James P et Bassam Alugili, j'ai fini par ajouter ces lignes de code à la méthode Startup.cs-> Configure.

 try
            {
                using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
                    .CreateScope())
                {

                    serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
                        .Database.Migrate();
                }
            }
            catch (Exception e)
            {
                var msg = e.Message;
                var stacktrace = e.StackTrace;
            }
10
bailando bailando

De plus, vous risquez de voir un impact négatif sur les performances si vous appelez cela dans le constructeur de votre contexte ... Après avoir déplacé EnsureCreated vers l'utilitaire setup.cs, j'ai constaté des améliorations considérables de mon temps de réponse. 

Note: J'utilise EFC et UWP.

0
visc