Mysql
 sql >> Database >  >> RDS >> Mysql

Come creare un inizializzatore per creare e migrare il database mysql?

Penso che tu sia praticamente lì:puoi cercare il codice sorgente per MigrateDatabaseToLatestVersion (è open source http://entityframework.codeplex.com/ ) - è piuttosto semplicistico, quello che fa praticamente è chiamare DbMigrator - Per quanto ho potuto vedere.

Tutto quello che devi fare sembra unire i due - usa l'uno o l'altro come base, aggiungi altre funzionalità lì dentro - penso che dovrebbe funzionare bene.

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)
    {
    }
}

chiamalo così...

Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>());

...in realtà, sovrascrivilo (dato che è un'implementazione generica) come stavi facendo per CreateDatabaseIfNotExists (hai solo un "parametro" extra per la configurazione) - e fornisci semplicemente il "seme".

class GumpDatabaseInitializer : CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>
{
    protected override void Seed(GumpDatabase context)
    {
        context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
    }
}

...e chiamalo qualcosa come

Database.SetInitializer(new GumpDatabaseInitializer());

MODIFICA: Sulla base dei commenti, DbMigrator non dovrebbe essere eseguito due volte. Controlla sempre (trascorre un po' di tempo) e fa un aggiornamento "vuoto" e va avanti. Tuttavia, per ogni evenienza, se desideri rimuoverlo e "controlla" prima di entrare - dovrebbe funzionare (cambia il pezzo simile sopra)...

var migrator = new DbMigrator(_configuration);
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
    if (migrator.GetPendingMigrations().Any())
        migrator.Update();

(questo è un ridondante / doppio controllo - uno degli if-s dovrebbe essere sufficiente. Metti una pausa lì - e vedi esattamente cosa sta succedendo, non dovrebbe entrare - una volta che Db è migrato. Come ho già detto, funziona bene quando ho provalo.

MODIFICA:

Sostituisci l'interno di InitializeDatabase con...

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();
}

Questo funziona intorno al non seeding (a metà strada), se la migrazione inizia prima. E le migrazioni devono essere al primo posto, altrimenti hai problemi.

Hai ancora bisogno di farlo correttamente - questo è il succo se non tutto ciò di cui potresti aver bisogno - ma in caso di problemi con MySQL ecc., probabilmente un po' di lavoro in più qui.

Nota: Il seeding ancora non chiama se hai un db, ma è vuoto. Il problema è la miscelazione dei due diversi inizializzatori. Quindi dovrai risolverlo, implementando ciò che Create... fa all'interno (quella chiamata che non possiamo chiamare) o qualcos'altro.