26

私は最近Entity Framework 5にアップグレードしたMVC4アプリケーションを持っており、開発スタイルからの移行を使用してデータベースを移動しようとしていますそれぞれの実行を削除して作成します。Entity Framework 5の移行:データベースの初期移行と単一シードの設定

これは、私のアプリ起動機能で行っていることです。

protected void Application_Start() 
{ 
    Database.SetInitializer(
     new MigrateDatabaseToLatestVersion< MyContext, Configuration >()); 
    ... 
} 

私は自分のリポジトリプロジェクトにEnable-Migrationsコマンドを実行したと私は経由予想通り、それはそれを作成したデータベースを削除すると、私は、しかし、それが作成されたファイルのみがConfiguration

だった、これは最初の移行ファイルを作成するだろうと思いました最初にコードを読み込み、データベースを設定ファイルからシードします。設定ファイルでは、私はそれは、ウェブサイトが起動し、重複すべてのシード・データを何度も何度も私のConfigurationファイルにするたびに、シード関数を実行しかしAddOrUpdate()

にすべてAdd()の機能を変更しました。

私は私が読んブログは、それは、私はそこにシード・データを置くことができるだろうが、それは誰もが私がDBをセットアップする方法を説明することができません

なかったことを示唆したとして、それはinitial migrationファイルを作成することを想像しコードでそれは一度だけ種まきますか?


LINK: The migrations blog post I followed


これは私がマイグレーションを実行するためroundhouseを使用するように切り替えたため、EFのmigrate.exeのを使用するための非常に興味深いですが。私はまだモデルに基づいて私の移行を足場にEFを使用していますが、私はSQLファイルに移行を書き込むための小さなコンソールアプリケーションを書いた。ラウンドハウスを使用して、自分のレーキ構築スクリプトを使って移行を実行します。もう少し複雑なプロセスがありますが、アプリケーションの起動時にEFを使用して移行を実行するよりもはるかに安定しています。

答えて

38

これはので、私は他人からのフィードバックに照らして、それを更新した人気のポストであることが判明しました。重要なことは、ConfigurationクラスのSeedメソッドが、アプリケーションが起動するたびに実行されるということです。これは、テンプレートメソッドのコメントが意味するものではありません。 Microsoftの誰かからの回答を参照してください。postなぜそれがあるのか​​ - Jason Learmouthに感謝します。

私のように、保留中の移行がある場合はデータベースの更新のみを実行したい場合は、もう少し作業を行う必要があります。 migrator.GetPendingMigrations()を呼び出すことで、保留中の移行がある場合はそのことがわかりますが、Seedメソッドが呼び出される前に保留中の移行のリストが消去されるため、ctorでその処理を行う必要があります。次のようにMigrations.Configurationクラスで行くこれを​​実装するコードは、次のとおりです。

internal sealed class Configuration : DbMigrationsConfiguration<YourDbContext> 
{ 
    private readonly bool _pendingMigrations; 

    public Configuration() 
    { 
     // If you want automatic migrations the uncomment the line below. 
     //AutomaticMigrationsEnabled = true; 
     var migrator = new DbMigrator(this); 
     _pendingMigrations = migrator.GetPendingMigrations().Any(); 
    } 

    protected override void Seed(MyDbContext context) 
    { 
     //Microsoft comment says "This method will be called after migrating to the latest version." 
     //However my testing shows that it is called every time the software starts 

     //Exit if there aren't any pending migrations 
     if (!_pendingMigrations) return; 

     //else run your code to seed the database, e.g. 
     context.Foos.AddOrUpdate(new Foo { bar = true}); 
    } 
} 

私は何人かの人々は、実際の移行コード「アップ」でシードコードを置くことが示唆されていることを指摘しなければなりません。これは機能しますが、新しい移行ごとにシードコードを入れることを覚えておく必要があることを意味します。しかし、移行ごとに種が変化するなら、それは良い方法かもしれません。

+0

実際のマイグレーションにシーディングを実装することなく、それを実行できる唯一の方法であるため、毎回実行されると思います。あなたのシードコードがマイグレーションのUp()の中にあった場合は、一度だけ実行されます。これは通常、データベースの変更をいくつか行い、スキーマのこの新しい部分にいくつかのデータを入れたいので、私にとっては直感的です。 – FRoZeN

+0

Ifこのメソッドを使用してシードメソッドを実行することはありません。私は今も、マイグレーションで播種をすることを好む - それが一度だけ実行されることを知っている。 – oldwizard

+0

こんにちは。実際には、最初のデータベースは移行とみなされます。つまり、データベースからデータベースへ移行します。しかし、私は移行にシードを持たせることの利点を見ることができます。 –

2

これは私が過去に疑問に思っていたものです。私は自分のSeedイベントにデータが入る特定のテーブルをデータベースに持っていますが、今ではSeedメソッド内に空白が1つしかないかどうかを確認するだけです。行がある場合、Seedメソッドは実行されません。間違いではありませんが、そのトリックはあります。

+1

これはデータの重複を防止するために機能しましたが、exit句を追加するハックな解決策のようです。私はそれを行うより良い方法があるかどうかを確認するために、もう少し質問を残しておきます – Neil

+0

私はそれがハックな解決であることに同意します - それは出口ではなく、その後、移行で移入する可能性のある追加の表のためにそれを繰り返すことができます。 – Richard

6

手動でマイグレーションを追加して、必要なシードコードを入力することができますか?パッケージマネージャコンソールで次のコマンドを実行します。

Add-Migration [Name] 

次に、migrationsフォルダに作成されたファイルを編集できます。

私のプロジェクトでは、コンテキスト設定のSeedメソッドでは、実際にはRichardのようにシードしています。私は本当に好みがありません。しかし、アプリケーションの起動時にデータベースに行が存在するかどうかをアプリケーションが確認する必要がないという点で、移行はより効率的でなければなりません。マイグレーションが実行されたかどうかを確認する必要があります。これは高速でなければなりません。

internal sealed class Configuration : DbMigrationsConfiguration<MyContext> 
{ 
    public Configuration() 
    { 
     // If you want automatic migrations as well uncomment below. 
     // You can use both manual and automatic at the same time, but I don't recommend it. 
     //AutomaticMigrationsEnabled = true; 
     //AutomaticMigrationDataLossAllowed = true; 
    } 

    protected override void Seed(MyContext context) 
    { 
     // This method will be called after migrating to the latest version. 

     // You can use the DbSet<T>.AddOrUpdate() helper extension method 
     // to avoid creating duplicate seed data. 

     context.FontFamilies.AddOrUpdate(
      f => f.Id, 
      new FontFamily { Id = 1, PcName = "Arial" }, 
      new FontFamily { Id = 2, PcName = "Times New Roman" }, 
     }); 

私はこれをグローバルで使用しています。asax:

public class MvcApplication : System.Web.HttpApplication 
{ 
    protected void Application_Start() 
    { 
     // Any migrations that haven't been applied before will 
     // automatically be applied on Application Pool restart 

     Database.SetInitializer<MyContext>(
      new MigrateDatabaseToLatestVersion<MyContext, 
      MyApp.Migrations.Configuration>() 
     ); 
    } 
} 
+0

これは答えとしてマークする必要があります。ヒントは、「AddOrUpdate」の主キーチェックによるオーバーロードです。私は最初にそれを認識しませんでした。 – Sven

2

this SO questionの答えは、アプリが実行されるたびにシードが実行される理由を説明しています。

私はジョン・スミスメソッドを使用しますが、私はこのようなの#ifブロック内の保留中の移行声明にチェックを入れている:私はシードメソッドをデバッグするよその方法は、常に私が再配置され実行さ

#if (!DEBUG) 
      if (!_pendingMigrations) return; 
#endif 

シードデータ - テスト中に削除するときに便利ですが、リリース時にはperfヒットは得られません。

関連する問題