sql >> Databáze >  >> RDS >> Mysql

Jak vytvořit inicializátor pro vytvoření a migraci databáze mysql?

Myslím, že jste tam skoro – můžete vyhledat zdrojový kód pro MigrateDatabaseToLatestVersion (je to open source http://entityframework.codeplex.com/ ) – je to docela zjednodušující, do značné míry to dělá volání DbMigrator - pokud jsem viděl.

Zdá se, že vše, co musíte udělat, je sloučit tyto dva - použít jeden nebo druhý jako základ, přidat tam další funkce - to by podle mě mělo fungovat dobře.

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

nazvěte to takto...

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

...ve skutečnosti to přepište (protože jde o obecnou implementaci), jako jste to dělali pro CreateDatabaseIfNotExists (máte jen extra 'param' pro konfiguraci) - a stačí dodat 'Seed'.

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

...a nazvěte to nějak jako

Database.SetInitializer(new GumpDatabaseInitializer());

UPRAVIT: Na základě komentářů - DbMigrator by neměl běžet dvakrát. Vždy to zkontroluje (stráví trochu času) a provede „prázdnou“ aktualizaci a pokračuje dál. Nicméně pro případ, že byste to chtěli odstranit a před zadáním „zkontrolovat“ – mělo by to fungovat (změňte podobný kus výše)...

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

(toto je redundantní / dvojitá kontrola - jedno z if-s by mělo stačit. Dejte tam přestávku - a uvidíte, co se přesně děje, nemělo by se to dostat dovnitř - jakmile je Db migrován. Jak jsem zmínil, funguje dobře, když otestujte to.

UPRAVIT:

Nahraďte vnitřek InitializeDatabase s...

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

Toto funguje kolem (napůl) nezasévání – pokud migrace proběhne jako první. A migrace musí být na prvním místě, jinak máte problémy.

Stále to musíte dělat správně - toto je podstata, pokud ne vše, co byste mohli potřebovat - ale pokud se vyskytnou nějaké problémy s MySQL atd., pravděpodobně zde bude ještě nějaká práce.

Poznámka: Still seeding nevolá, pokud máte db, ale je prázdný. Problém je smíchání dvou různých inicializátorů. Takže to budete muset vyřešit - buď implementací toho, co Create... dělá uvnitř (to volání nemůžeme zavolat), nebo něčím jiným.



  1. Jak auto-inkrementovat v rámci podmnožiny tabulky MYSQL

  2. Alternativy PGTune - Konfigurace ClusterControl PostgreSQL

  3. Injekce SQL, která obchází mysql_real_escape_string()

  4. Jak získat Insert id v MSSQL v PHP?