Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como criar inicializador para criar e migrar banco de dados mysql?


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.