web-dev-qa-db-fra.com

Entity Framework, Migrations d'application automatique

J'utilise l'approche Entity Framework Code First avec AutomaticMigrationsEnabled = true:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<DbContext, MigrateDBConfiguration>());
//////////////////////////////////

public class MigrateDBConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration<DbContext>
{
    public MigrateDBConfiguration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    }
}

La première exécution du projet crée la base de données et les tables comme prévu. Après avoir changé mon modèle en ajoutant ou en supprimant des champs, j'ai exécuté Add-Migration. La classe Migration a été générée mais après l'exécution du projet, cette exception se produit:

Une exception de type "System.InvalidOperationException" s'est produite dans EntityFramework.dll mais n'a pas été gérée dans le code utilisateur

Informations supplémentaires: Le modèle qui soutient le contexte "DBContext" a changé depuis la création de la base de données.

EDIT: Selon les conseils de la réponse de arturo menchaca J'ai changé mon code comme ceci:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<DBContext, MigrateDBConfiguration<DBContext>>());

...

Après la modification, cette exception se produit:

Il existe déjà un objet nommé "MyTable" dans la base de données.

Comment puis-je appliquer ma migration de base de données?

13
Fred

Enfin, j'ai trouvé une solution à mon problème. J'appelle cette méthode à chaque démarrage d'application:

public void InitializeDatabase(DataAccessManager context)
{
    if (!context.Database.Exists() || !context.Database.CompatibleWithModel(false))
    {
        var configuration = new DbMigrationsConfiguration();
        var migrator = new DbMigrator(configuration);
        migrator.Configuration.TargetDatabase = new DbConnectionInfo(context.Database.Connection.ConnectionString, "System.Data.SqlClient");
        var migrations = migrator.GetPendingMigrations();
        if (migrations.Any())
        {
            var scriptor = new MigratorScriptingDecorator(migrator);
            var script = scriptor.ScriptUpdate(null, migrations.Last());

            if (!string.IsNullOrEmpty(script))
            {
                context.Database.ExecuteSqlCommand(script);
            }
        }
    }
}
15
Fred

Migrations automatiques signifie que vous n'avez pas besoin d'exécuter la commande add-migration Pour vos modifications dans les modèles, mais vous devez exécuter la commande update-database Manuellement.

Si Migrations automatiques est activé lorsque vous appelez update-database, S'il y a des modifications en attente dans vos modèles, une migration "automatique" sera ajoutée et la base de données sera mise à jour.

Si vous voulez que votre base de données soit mise à jour sans avoir besoin d'appeler la commande update-database, Vous pouvez ajouter la méthode Database.SetInitializer(...) dans OnModelCreating() sur votre contexte, comme ceci:

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, MigrateDBConfiguration>());
    }

    ...
}

public class MigrateDBConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration<MyContext>
{
    ...

Notez que vous devez déclarer DbMigrationsConfiguration et MigrateDatabaseToLatestVersion avec votre contexte réel, pas le DbContext par défaut.

15
Arturo Menchaca

Si vous avez modifié vos entités, vous devez d'abord exécuter add-migration pour créer le script de migration.

Après cela, dans votre Global.asax

vous devez avoir un code comme celui-ci

        var configuration = new MyProject.Configuration();
        var migrator = new System.Data.Entity.Migrations.DbMigrator(configuration);            

        migrator.Update();

chaque fois que vous exécutez votre projet asp.net, il vérifie si vous avez une nouvelle migration à exécuter et à exécuter update-database automatiquement pour vous.

3
gorums