sql >> Database >  >> RDS >> Mysql

Hoe maak je een initializer om een ​​mysql-database te maken en te migreren?

Ik denk dat je er zo ongeveer bent - je kunt de broncode opzoeken voor MigrateDatabaseToLatestVersion (het is open source http://entityframework.codeplex.com/ ) - het is vrij simplistisch, wat het ongeveer doet, is de DbMigrator aanroepen - voor zover ik kon zien.

Het enige wat je hoeft te doen lijkt de twee samen te voegen - gebruik de een of de ander als basis, voeg daar andere functionaliteit aan toe - dat zou volgens mij prima moeten werken.

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

noem het zo...

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

...eigenlijk, overschrijf het (omdat het een generieke implementatie is) zoals je deed voor CreateDatabaseIfNotExists (je hebt gewoon extra 'param' voor configuratie) - en geef gewoon het 'Seed' aan.

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

...en noem het zoiets als

Database.SetInitializer(new GumpDatabaseInitializer());

BEWERKEN: Op basis van de opmerkingen - DbMigrator mag niet twee keer worden uitgevoerd. Het controleert altijd (neemt wat tijd in beslag) en voert een 'lege' update uit en gaat verder. Maar voor het geval je dat wilt verwijderen en 'aanvinken' voordat je naar binnen gaat - dit zou moeten werken (verander het soortgelijke stuk hierboven)...

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

(dit is een redundante / dubbele controle - een van de if-s zou voldoende moeten zijn. Zet daar een pauze - en kijk precies wat er gebeurt, het zou niet binnen moeten komen - zodra Db is gemigreerd. Zoals ik al zei, werkt prima als ik test het.

BEWERKEN:

Vervang de binnenkant van InitializeDatabase met...

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

Dit werkt rond (halverwege) niet-seeding - als migratie eerst gaat. En migraties moeten voorop staan, anders heb je problemen.

Je moet het nog steeds goed doen - dit is de essentie, zo niet alles wat je nodig hebt - maar als er problemen zijn met MySQL enz., waarschijnlijk wat meer werk hier.

Opmerking: Seeding roept nog steeds niet op als je een db hebt, maar het is leeg. Het probleem is het mengen van de twee verschillende initializers. Dus je zult dat moeten oplossen - ofwel door te implementeren wat Create... binnen doet (die oproep kunnen we niet bellen) of iets anders.



  1. SQL Server-uitvoerclausule in een scalaire variabele

  2. Spring Data JPA Auditing werkt niet voor de JpaRepository-updatemethode met @Modifying-annotatie, waarom?

  3. TreeView-knooppunten opnieuw rangschikken met slepen en neerzetten

  4. SQLite primaire sleutel