sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo crear un inicializador para crear y migrar una base de datos mysql?

Creo que ya está allí:puede buscar el código fuente para MigrateDatabaseToLatestVersion (es de código abierto http://entityframework.codeplex.com/ ) - es bastante simple, lo que hace es llamar al DbMigrator - Por lo que pude ver.

Parece que todo lo que tiene que hacer es fusionar los dos:use uno u otro como base, agregue otra funcionalidad allí, creo que debería funcionar bien.

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

llámalo así...

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

... en realidad, anúlelo (ya que es una implementación genérica) como lo estaba haciendo para CreateDatabaseIfNotExists (solo tiene un 'parámetro' adicional para la Configuración), y solo proporcione la 'Semilla'.

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

...y llámalo algo como

Database.SetInitializer(new GumpDatabaseInitializer());

EDITAR: Según los comentarios, DbMigrator no debería ejecutarse dos veces. Siempre verifica (dedica un poco de tiempo) y realiza una actualización 'en blanco' y continúa. Sin embargo, por si acaso, si desea eliminar eso y 'verificar' antes de ingresar, esto debería funcionar (cambie la pieza similar anterior) ...

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

(esta es una verificación redundante / doble:uno de los if-s debería ser suficiente. Ponga un descanso allí, y vea exactamente lo que está sucediendo, no debería ingresar, una vez que se migra Db. Como mencioné, funciona bien cuando pruébalo.

EDITAR:

Reemplace el interior de 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();
}

Esto funciona alrededor de la no siembra (a medias), si la migración se realiza primero. Y las migraciones tienen que ser lo primero, de lo contrario tienes problemas.

Aún debe hacerlo correctamente; esta es la esencia, si no todo lo que podría necesitar, pero si hay algún problema con MySQL, etc., probablemente haya más trabajo de piernas aquí.

Nota: Todavía la siembra no llama si tiene un db, pero está vacío. El problema es mezclar los dos inicializadores diferentes. Así que tendrás que resolver eso, ya sea implementando lo que Create... hace dentro (esa llamada que no podemos llamar) o algo más.