web-dev-qa-db-ja.com

Entity Framework 4.3でデータを増分的にシードする最良の方法

既存のデータベースでEntity Framework 4.3を使用しており、いくつかのシナリオに対応しようとしています。

最初に、データベースを削除する場合、最初からEFを再作成します-これにCreateDatabaseIfNotExistsデータベース初期化子を正常に使用しました。

第二に、モデルを更新し、データベースが既に存在する場合、データベースを自動的に更新したいです-これにEntity Framework 4.3 Migrationsを使用しました。

だからここに私の質問です。いくつかの参照データを必要とするモデルに新しいテーブルを追加するとします。これは、データベースイニシャライザの実行時と移行の実行時の両方でこのデータを作成するための最良の方法です。私の望みは、データベースを最初から作成するとき、および移行の実行の結果としてデータベースが更新されるときにデータが作成されることです。

いくつかのEF移行の例では、人々は移行のUPメソッドでSQL()関数を使用してシードデータを作成しましたが、可能であればコンテキストを使用してシードデータを作成します(ほとんどのデータベース初期化の例で見られるように) EFの概念全体がそれを抽象化するときに純粋なSQLを使用するのは私には奇妙に思えます。 UPメソッドでコンテキストを使用しようとしましたが、何らかの理由で、テーブルを作成する呼び出しの直下にシードデータを追加しようとしたときに、移行で作成されたテーブルが存在するとは思われませんでした。

どんな知恵も大歓迎です。

41
Jim Culverwell

エンティティを使用してデータをシードする場合は、移行構成でSeedメソッドを使用する必要があります。新しいプロジェクトを生成する場合Enable-Migrationsこの構成クラスを取得します。

internal sealed class Configuration : DbMigrationsConfiguration<YourContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(CFMigrationsWithNoMagic.BlogContext 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. E.g.
        //
        //    context.People.AddOrUpdate(
        //      p => p.FullName,
        //      new Person { FullName = "Andrew Peters" },
        //      new Person { FullName = "Brice Lambson" },
        //      new Person { FullName = "Rowan Miller" }
        //    );
        //
    }
}

マイグレーションがデータをシードする方法は、非常に基本的なシードに使用されることになっているため、あまり効率的ではありません。新しいバージョンへのすべての更新は、セット全体を通過し、既存のデータの更新または新しいデータの挿入を試みます。 AddOrUpdate拡張メソッドを使用しない場合、データがまだ存在しない場合にのみ、データがデータベースにシードされることを手動で確認する必要があります。

大量のデータをシードする必要があるため、効率的なシード方法が必要な場合は、commonでより良い結果が得られます。

public partial class SomeMigration : DbMigration
{
    public override void Up()
    {
        ...
        Sql("UPDATE ...");
        Sql("INSERT ...");
    }

    public override void Down()
    {
        ...
    }
}
55
Ladislav Mrnka

Sql()メソッドでUp()呼び出しを使用することはお勧めしません。なぜなら、(IMO)これは実際には、シードコードではなく、組み込み関数がない実際の移行コードを対象としているからです。 。

シードデータは将来(スキーマが変更されない場合でも)変更される可能性があると考えているため、シード関数内のすべての挿入の周りに「ディフェンシブ」チェックを記述して、操作が実行されないことを確認します以前。

3つのエントリで始まる「タイプ」テーブルがあり、その後4番目を追加するシナリオを考えます。これに対処するために「移行」は必要ありません。

Seed()を使用すると、操作する完全なコンテキストも得られます。これは、Ladislavが示したSql()メソッドでプレーンなsql文字列を使用するよりもはるかに優れています。

また、移行コードとシードコードの両方に組み込みEFメソッドを使用する利点は、データベース操作がプラットフォームに依存しないことです。これは、スキーマの変更とクエリをOracle、Postgreなどで実行できることを意味します。実際の生のSQLを記述する場合、不必要に自分をロックしてしまう可能性があります。

EFを使用している人の90%がSQL Serverにしかヒットしないため、これについてはあまり気にしないかもしれませんが、ソリューションについては別の見方をするためにそこに投げています。

32
Roger