Myślę, że już tam jesteś — możesz wyszukać kod źródłowy dla MigrateDatabaseToLatestVersion
(to open source http://entityframework.codeplex.com/
) - to dość uproszczone, to, co robi, to wywołanie DbMigrator
- o ile mogłem zobaczyć.
Wydaje się, że wszystko, co musisz zrobić, to połączyć te dwa - użyj jednego lub drugiego jako podstawy, dodaj tam inną funkcjonalność - myślę, że powinno to działać dobrze.
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)
{
}
}
nazwij to tak...
Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>());
...właściwie nadpisz go (ponieważ jest to ogólna implementacja), tak jak robiłeś to dla CreateDatabaseIfNotExists
(po prostu masz dodatkowy 'param' dla konfiguracji) - i po prostu podaj 'Seed'.
class GumpDatabaseInitializer : CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>
{
protected override void Seed(GumpDatabase context)
{
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
}
}
...i nazwij to mniej więcej
Database.SetInitializer(new GumpDatabaseInitializer());
EDYTUJ: Na podstawie komentarzy - DbMigrator nie powinien być uruchamiany dwukrotnie. Zawsze sprawdza (poświęca trochę czasu) i wykonuje „pustą” aktualizację i rusza dalej. Jednak na wszelki wypadek, jeśli chcesz to usunąć i „sprawdzić” przed wejściem - to powinno zadziałać (zmień podobny element powyżej)...
var migrator = new DbMigrator(_configuration);
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
if (migrator.GetPendingMigrations().Any())
migrator.Update();
(jest to nadmiarowe / podwójne sprawdzenie - jeden z if-s powinien wystarczyć. Umieść tam przerwę - i zobacz dokładnie, co się dzieje, nie powinno się dostać - po migracji Db. Jak wspomniałem, działa dobrze, gdy ja przetestuj to.
EDYTUJ:
Zastąp wnętrze InitializeDatabase
z...
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();
}
Działa to w ramach (w połowie) nie-seedingu — jeśli migracja jest pierwsza. A migracje muszą być pierwsze, inaczej masz problemy.
Nadal musisz to zrobić poprawnie - to jest sedno, jeśli nie wszystko, czego możesz potrzebować - ale jeśli jakieś problemy z MySQL itp., prawdopodobnie trochę więcej działa tutaj.
Uwaga: Nadal seedowanie nie wywołuje, jeśli masz bazę danych, ale jest ona pusta. Problem polega na mieszaniu dwóch różnych inicjatorów. Musisz więc to rozpracować — albo implementując to, co Create… robi wewnątrz (tego wywołania nie możemy wywołać), albo coś innego.