私はあなたがほとんどそこにいると思います-あなたはMigrateDatabaseToLatestVersion
のソースコードを検索することができます (オープンソースの http://entityframework.codeplex.com/
)-かなり単純化されています。ほとんどの場合、DbMigrator
と呼ばれます。 -私が見る限り。
あなたがしなければならないのは、2つをマージすることです-どちらか一方をベースとして使用し、そこに他の機能を追加します-それはうまくいくはずです。
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)
{
}
}
このように呼んでください...
Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>());
...実際には、CreateDatabaseIfNotExists
の場合と同じように、(一般的な実装であるため)オーバーライドします。 (構成用に追加の「param」があります)-そして「シード」を指定するだけです。
class GumpDatabaseInitializer : CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>
{
protected override void Seed(GumpDatabase context)
{
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
}
}
...そしてそれを
のようなものと呼びますDatabase.SetInitializer(new GumpDatabaseInitializer());
編集: コメントに基づく-DbMigratorは2回実行しないでください。常にチェックし(少し時間を費やし)、「空白」の更新を実行して次に進みます。ただし、それを削除して入力する前に「チェック」したい場合に備えて、これは機能するはずです(上記の同様の部分を変更してください)...
var migrator = new DbMigrator(_configuration);
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
if (migrator.GetPendingMigrations().Any())
migrator.Update();
(これは冗長/ダブルチェックです-if-sの1つで十分です。そこに休憩を入れて-Dbが移行されたら、何が起こっているのかを正確に確認してください-入らないようにしてください。前述のように、私がテストしてください。
編集:
InitializeDatabase
の内部を置き換えます と...
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();
}
これは、(途中で)シードされないことを回避します-移行が最初に行われる場合。そして、移行を最初に行う必要があります。そうしないと、問題が発生します。
あなたはまだそれを適切に行う必要があります-これはあなたが必要とするかもしれないすべてではないにしても要点です-しかしMySQLなどで問題があれば、おそらくここでもう少し足がかりです。
注: それでも、dbがある場合はシードは呼び出されませんが、空です。問題は、2つの異なる初期化子の混合です。したがって、Create ...が内部で行うこと(呼び出すことはできません)または他の何かを実装することによって、それを解決する必要があります。