Je pense que vous y êtes à peu près - vous pouvez rechercher le code source pour MigrateDatabaseToLatestVersion
(c'est open source http://entityframework.codeplex.com/
) - c'est assez simpliste, ce qu'il fait à peu près, c'est appeler le DbMigrator
- aussi loin que je pouvais voir.
Tout ce que vous avez à faire semble être de fusionner les deux - utilisez l'un ou l'autre comme base, ajoutez d'autres fonctionnalités là-dedans - cela devrait bien fonctionner, je pense.
class CreateAndMigrateDatabaseInitializer<TContext, TConfiguration> : CreateDatabaseIfNotExists<TContext>, IDatabaseInitializer<TContext>
where TContext : DbContext
where TConfiguration : DbMigrationsConfiguration<TContext>, new()
{
private readonly DbMigrationsConfiguration _configuration;
public CreateAndMigrateDatabaseInitializer()
{
_configuration = new TConfiguration();
}
public CreateAndMigrateDatabaseInitializer(string connection)
{
Contract.Requires(!string.IsNullOrEmpty(connection), "connection");
_configuration = new TConfiguration
{
TargetDatabase = new DbConnectionInfo(connection)
};
}
void IDatabaseInitializer<TContext>.InitializeDatabase(TContext context)
{
Contract.Requires(context != null, "context");
var migrator = new DbMigrator(_configuration);
migrator.Update();
// move on with the 'CreateDatabaseIfNotExists' for the 'Seed'
base.InitializeDatabase(context);
}
protected override void Seed(TContext context)
{
}
}
appelez-le comme ça...
Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>());
... en fait, remplacez-le (puisqu'il s'agit d'une implémentation générique) comme vous le faisiez pour CreateDatabaseIfNotExists
(vous avez juste un "param" supplémentaire pour la configuration) - et fournissez simplement la "graine".
class GumpDatabaseInitializer : CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>
{
protected override void Seed(GumpDatabase context)
{
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
}
}
...et appelez-le quelque chose comme
Database.SetInitializer(new GumpDatabaseInitializer());
MODIF : D'après les commentaires - DbMigrator ne devrait pas s'exécuter deux fois. Il vérifie toujours (passe un peu de temps) et fait une mise à jour "vierge" et passe à autre chose. Cependant, juste au cas où vous voudriez supprimer cela et "vérifier" avant d'entrer - cela devrait fonctionner (changez la pièce similaire ci-dessus)...
var migrator = new DbMigrator(_configuration);
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
if (migrator.GetPendingMigrations().Any())
migrator.Update();
(il s'agit d'une redondance / double vérification - l'un des if-s devrait suffire. Faites une pause ici - et voyez exactement ce qui se passe, cela ne devrait pas entrer - une fois que Db est migré. Comme je l'ai mentionné, fonctionne bien quand je testez-le.
MODIF :
Remplacez l'intérieur de InitializeDatabase
avec...
var doseed = !context.Database.Exists();
// && new DatabaseTableChecker().AnyModelTableExists(context);
// check to see if to seed - we 'lack' the 'AnyModelTableExists' - could be copied/done otherwise if needed...
var migrator = new DbMigrator(_configuration);
// if (doseed || !context.Database.CompatibleWithModel(throwIfNoMetadata: false))
if (migrator.GetPendingMigrations().Any())
migrator.Update();
// move on with the 'CreateDatabaseIfNotExists' for the 'Seed'
base.InitializeDatabase(context);
if (doseed)
{
Seed(context);
context.SaveChanges();
}
Cela fonctionne autour du non-ensemencement (à mi-chemin) - si la migration commence en premier. Et les migrations doivent être les premières, sinon vous avez des problèmes.
Vous devez toujours le faire correctement - c'est l'essentiel sinon tout ce dont vous pourriez avoir besoin - mais en cas de problème avec MySQL, etc., probablement un peu plus de travail ici.
Remarque : L'ensemencement n'appelle toujours pas si vous avez une base de données, mais elle est vide. Le problème est le mélange des deux initialiseurs différents. Vous devrez donc résoudre ce problème - soit en implémentant ce que Create... fait à l'intérieur (cet appel que nous ne pouvons pas appeler) ou autre chose.