web-dev-qa-db-ja.com

コードファーストで、存在しないデータベースを常に初期化するように強制しますか?

時々、開発データベースを削除して、EFコードファーストアプリケーションを実行します。エラーが発生します:

ログインで要求されたデータベース「AssessmentSystem」を開くことができません。ログインに失敗しました。ユーザー「AssessmentAdmin」のログインに失敗しました。

これは、 このページ が言うように、DbContextが「コンテキストが初めて使用されるときにAppDomainごとに1回」DB初期化ロジックを実行するだけだからだと思います。これは、データベースを削除した場合にEFにデータベースを再作成させるために、IISアプリケーションプールをリサイクルする必要があることを意味します。

データベースにアクセスしようとするたびにDB初期化コードを実行する方法はありますか?したがって、DBが存在するかどうかを常に確認し、存在しない場合は、以前に削除したデータベースにアクセスしたのと同じAppDomainを使用している場合でも、DBを開こうとするのではなく作成しますか?

この初期化チェックをすべてのクエリで実行したいので、Application_Startで実行しても十分ではない場合が多いことに注意してください。理想的には、いくつかのDBデータをロードし、DBを削除してから、いくつかのDBデータをロードできるようにしたいと思います。そうすれば、アプリケーションを再起動しなくてもDBが再作成されます(基本的には、Webページをリロードするだけです。一部のDBデータをロードします)。

17
Jez

Initializerは、データベースにアクセスする必要があるときに実行されるため、アプリの起動時にデータベースを作成する場合は、次のいずれかを使用します。

_    context.Database.Initialize(true); //If set to true the initializer is run even if it has already been run.       
    context.Database.Create()
_

http://msdn.Microsoft.com/en-us/library/system.data.entity.database.initialize(v = vs.103).aspx

CreateDatabaseIfNotExistsデータベースが存在しない場合にのみ、データベースを再作成し、オプションでデータを再シードするIDatabaseInitializerの実装。データベースをシードするには、派生クラスを作成し、Seedメソッドをオーバーライドします。

_Database.SetInitializer<MyContext>(new CreateDatabaseIfNotExists<MyContext>());
_

http://msdn.Microsoft.com/en-us/library/gg679221(v = vs.103).aspx

DropCreateDatabaseIfModelChangesデータベースの作成後にモデルが変更された場合にのみ、データベースを削除、再作成し、オプションでデータを再シードするIDatabaseInitializerの実装。これは、ストアモデルのハッシュを作成時にデータベースに書き込み、そのハッシュを現在のモデルから生成されたハッシュと比較することで実現されます。データベースをシードするには、派生クラスを作成し、Seedメソッドをオーバーライドします。

初期化戦略では、オプションでデータベースの存在を確認し、新しいデータベースを作成して、データベースにデータをシードできます。デフォルトの戦略は、CreateDatabaseIfNotExistsのインスタンスです。

Database.SetInitializer(new DropCreateDatabaseIfModelChanges());

これは、データベースを削除する権限があることを前提としていることに注意してください。

http://msdn.Microsoft.com/en-us/library/gg679604(v = vs.103).aspx

DropCreateDatabaseAlways

アプリケーションドメインでコンテキストが初めて使用されるときに、データベースを常に再作成し、オプションでデータを再シードするIDatabaseInitializerの実装。データベースをシードするには、派生クラスを作成し、Seedメソッドをオーバーライドします。

_Database.SetInitializer<MyContext>(new DropCreateDatabaseAlways<MyContext>());
_

http://msdn.Microsoft.com/en-us/library/gg679506(v = vs.103).aspx

追跡する場合は、移行を確認し、DBに加えた変更を以前の状態に戻すことをお勧めします http:/ /msdn.Microsoft.com/hr-hr/data/jj591621

[〜#〜]更新[〜#〜]

_context.Database.Initialize(true);
_

パラメーターforceがtrueに設定されている場合、初期化子は、以前に実行されたかどうかに関係なく実行されます。これは、アプリの実行中にデータベースが削除され、再初期化する必要がある場合に役立ちます。

MVCアプリケーションの場合、Global.asaxApplication_Start()メソッドにセクションを追加します

_protected void Application_Start() {

     Database.SetInitializer<MyContext>(new DropCreateDatabaseAlways<MyContext>()); 

     // Forces initialization of database on model changes.
     using (var context= new MyContext()) {
          context.Database.Initialize(force: true);
     }    
}
_

また、カスタム初期化子を使用することもできます。

_public class MyDbInit : DropCreateDatabaseAlways<MyContext>
{

}
_

その後、

_Database.SetInitializer(new MyDbInit());
_

UPDATE 2

DeleteDBOnEveryRequestという名前の新しい空のMVC4アプリケーションを作成します。 Global.asaxApplication_startに以下を入力します

_protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            Database.SetInitializer<BlogContext>(new DropCreateDatabaseAlways<BlogContext>());    

            using (var context = new BlogContext())
            {
                context.Database.Initialize(force: true);
            }    
        }
_

2つのアクションでDatabaseControllerという新しいコントローラーを作成します。

Accessアクションで、DBを削除し、Recreatedアクションにリダイレクトします。以前に削除されたDBを作成する場所。

_namespace DeleteDBOnEveryRequest.Controllers
{
    public class DatabaseController : Controller
    {
        public ActionResult Access()
        {
            using (var context = new BlogContext())
            {
                context.Database.Delete();
            } 
            return RedirectToAction("Recreated");
        }

        public ActionResult Recreated()
        {
            using (var context = new BlogContext())
            {
                context.Database.Initialize(force: true);                
            }
            return View();
        }
    }
}
_

これはあなたが望んでいたものですか?

36
Matija Grcic