Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie erstelle ich einen Initialisierer, um eine MySQL-Datenbank zu erstellen und zu migrieren?

Ich denke, Sie sind ziemlich genau dort – Sie können den Quellcode für MigrateDatabaseToLatestVersion nachschlagen (Es ist Open Source http://entityframework.codeplex.com/ ) - es ist ziemlich einfach, was es ziemlich genau macht, ist den DbMigrator zu nennen - Soweit ich sehen konnte.

Alles, was Sie tun müssen, scheint, die beiden zusammenzuführen - das eine oder andere als Basis zu verwenden, andere Funktionen hinzuzufügen - das sollte meiner Meinung nach gut funktionieren.

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

nenne es so...

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

...überschreiben Sie es eigentlich (da es sich um eine generische Implementierung handelt), wie Sie es für CreateDatabaseIfNotExists getan haben (Sie haben nur ein zusätzliches 'param' für die Konfiguration) - und geben Sie einfach den 'Seed' an.

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

... und nennen Sie es so etwas wie

Database.SetInitializer(new GumpDatabaseInitializer());

BEARBEITEN: Basierend auf den Kommentaren sollte DbMigrator nicht zweimal ausgeführt werden. Es prüft immer (verbringt ein wenig Zeit) und führt ein "leeres" Update durch und fährt fort. Aber nur für den Fall, wenn Sie das entfernen und vor dem Betreten "überprüfen" möchten - das sollte funktionieren (ändern Sie das ähnliche Stück oben) ...

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

(Dies ist eine redundante / doppelte Überprüfung - eines der if-s sollte ausreichen. Legen Sie dort eine Pause ein - und sehen Sie genau, was passiert, es sollte nicht hineinkommen - sobald Db migriert ist. Wie ich erwähnt habe, funktioniert es gut, wenn ich testen.

BEARBEITEN:

Ersetzen Sie das Innere von InitializeDatabase mit...

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

Dies funktioniert um das (halbe) Nicht-Seeding herum - wenn die Migration zuerst geht. Und Migrationen müssen an erster Stelle stehen, sonst gibt es Probleme.

Sie müssen es immer noch richtig machen - das ist das Wesentliche, wenn nicht alles, was Sie brauchen - aber wenn es Probleme mit MySQL usw. gibt, hier wahrscheinlich etwas mehr Beinarbeit.

Hinweis: Das Seeding ruft immer noch nicht auf, wenn Sie eine DB haben, aber sie ist leer. Das Problem ist das Mischen der beiden verschiedenen Initialisierer. Sie müssen das also herausfinden - entweder indem Sie implementieren, was Create... im Inneren tut (diesen Aufruf können wir nicht aufrufen) oder etwas anderes.