1

2つのサービスプロジェクト間で共有されるアセンブリにDbContextがあります。VisualStudioでデバッグを開始するように両方のプロジェクトを設定しています。DatabaseInitializerこれにより、各サービスのが起動時にデータベースを更新しようとする競合状態が発生します。

これを防ぐために、が自動的に登録されDbContextないように次のように変更しました。DatabaseIntializer

public EntityContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer<EntityContext>(null);
    }
}

自分のを参照するすべてのプロジェクトでその呼び出しを複製する必要がないように、DatabaseInitializer内部自体を無効にしたかったのですが、読んだ内容に基づいて、オーバーライドがそれを行う方法のようでした。DbContextSetInitializer()DbContextOnModelCreating()

これにより、DatabaseInitializerが自動的に実行されなくなりますが、データベースを更新するために手動で実行できる別のプロジェクトを作成したいと思いました。だから私は次のようなことをしました:

static void Main(string[] args)
{
    Database.SetInitializer(new CreateDatabaseIfNotExists<EntityContext>());
    new EntityContext().Database.Initialize(true);
}

問題は、これが機能していないように見えることです。OnModelCreating()メソッドで設定されたnull初期化子は、他のへの呼び出しで指定したものを明らかにオーバーライドしますSetInitializer()SetIntializer(null)クラスの静的コンストラクターに呼び出しを移動して、EntityContext最初に呼び出されることを保証しても、それでも機能しません。それが機能する唯一の方法は、次のように初期化子を手動で呼び出す場合です。

static void Main(string[] args)
{
    new CreateDatabaseIfNotExists<EntityContext>()
        .InitializeDatabase(new EntityContext());
}

しかしDatabaseInitializer.InitializeDatabase()、Entity Frameworkインフラストラクチャがそれを呼び出すことになっているため、直接呼び出すことは正しくないようです。

これはEFコードファーストのバグですか?これを行うための「正しい」方法は何ですか?

更新:パッケージマネージャーコンソールコマンドを使用してデータベーススクリプトを手動で作成するUpdate-Database方が、プログラムでデータベースを更新しようとするこの厄介なプロジェクトよりも優れたソリューションであると判断しました。

4

1 に答える 1

1

これは、初期化子を無効にする呼び出しの後に初期化子を設定する呼び出しが行われる限り、機能するはずです。あなたの場合、OnModelCreatingも静的EntityContext初期化子もそれを行いません。静的初期化子は、EntityContextを初めて使用するときにのみ呼び出されます。この例では、SetInitializerの呼び出しが完了するまで呼び出されません。

SetInitializerを呼び出す前に、静的初期化子を強制的に呼び出すことを検討できます。たとえば、これは機能するはずです。

using (var context = new EntityContext())
{
    Database.SetInitializer(new CreateDatabaseIfNotExists<EntityContext>());
    context.Database.Initialize(true);
}
于 2012-11-01T20:12:37.730 に答える