Acho que você está lá - você pode pesquisar o código-fonte para
MigrateDatabaseToLatestVersion
(é de código aberto http://entityframework.codeplex.com/
) - é bem simplista, o que ele faz é chamar o DbMigrator
- tanto quanto eu podia ver. Tudo o que você precisa fazer é mesclar os dois - use um ou outro como base, adicione outra funcionalidade lá - isso deve funcionar bem, eu acho.
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)
{
}
}
chame assim...
Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>());
... na verdade, substitua-o (já que é uma implementação genérica) como você estava fazendo para
CreateDatabaseIfNotExists
(você só tem 'param' extra para Configuração) - e apenas forneça a 'Seed'. class GumpDatabaseInitializer : CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>
{
protected override void Seed(GumpDatabase context)
{
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
}
}
... e chamá-lo de algo como
Database.SetInitializer(new GumpDatabaseInitializer());
EDITAR: Com base nos comentários - o DbMigrator não deve ser executado duas vezes. Ele sempre verifica (gasta um pouco de tempo) e faz uma atualização 'em branco' e segue em frente. No entanto, caso você queira remover isso e 'verificar' antes de entrar - isso deve funcionar (altere a parte semelhante acima) ...
var migrator = new DbMigrator(_configuration);
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
if (migrator.GetPendingMigrations().Any())
migrator.Update();
(esta é uma verificação redundante / dupla - um dos if-s deve ser suficiente. Coloque uma pausa lá - e veja exatamente o que está acontecendo, não deve entrar - uma vez que o Db é migrado. Como mencionei, funciona bem quando eu teste-o.
EDITAR:
Substitua o interior de
InitializeDatabase
com... 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();
}
Isso funciona em torno de (meio caminho) não-semeadura - se a migração for primeiro. E as migrações têm que ser as primeiras, caso contrário você terá problemas.
Você ainda precisa fazer isso corretamente - esta é a essência, se não tudo o que você pode precisar - mas se houver algum problema com o MySQL etc., provavelmente mais alguns trabalhos de perna aqui.
Observação: Ainda a propagação não chama se você tiver um banco de dados, mas está vazio. O problema é misturar os dois inicializadores diferentes. Então você terá que resolver isso - seja implementando o que Create... faz dentro (aquela chamada que não podemos chamar) ou qualquer outra coisa.