强制代码优先始终初始化不存在的数据库? [英] Forcing code-first to always initialize a non-existent database?

查看:114
本文介绍了强制代码优先始终初始化不存在的数据库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时我会删除我的开发数据库并运行我的EF代码优先应用程序。我会得到错误:


无法打开登录请求的数据库AssessmentSystem。登录失败。
用户'AssessmentAdmin'登录失败。


我认为这是因为 DbContext 只运行数据库初始化逻辑首次使用上下文时每AppDomain一次,如这个页面说。这意味着我需要回收IIS应用程序池以获取EF重新创建我的数据库,如果我删除它。



有没有什么办法可以让DB初始化代码运行每次我尝试访问数据库?所以,它将始终检查数据库是否存在,如果不存在,创建它而不是试图打开它,即使它使用与之前访问的数据库相同的AppDomain我现在已经删除了



请注意,我希望这个初始化检查在每个查询上完成,所以即使在 Application_Start 不够经常理想情况下,我想要加载一些数据库数据,删除数据库,然后加载一些数据库数据,它将重新创建数据库,而我甚至不需要重新启动应用程序(基本上我只需要重新加载网页,加载一些DB数据)。

解决方案

初始化程序在需要访问数据库时执行,你想在应用程序开始创建数据库,使用以下任何东西:

  context.Database.Initialize(true); //如果设置为true,则初始化程序即使已经运行,也会运行。 
context.Database.Create()

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



CreateDatabaseIfNotExists
IDatabaseInitializer的实现,只有数据库不存在,才能重新创建数据库,并可选择重新种数据库。要种子数据库,创建一个派生类并重写Seed方法。

  Database.SetInitializer&MyContext>(new CreateDatabaseIfNotExists< MyContext> ;()); 

http://msdn.microsoft.com/en-us/library/gg679221(v = vs103).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 = vs103).aspx



如果您要跟踪,请将您对DB的更改还原到以前的状态 Migrations :/ / / / />

更新

  context.Database.Initialize(true) ; 




如果参数force设置为true,则初始化程序将运行
无论是否已经运行。如果在应用程序运行时删除数据库,并且需要重新初始化
,那么这可以是


对于MVC应用程序,在 Global.asax



中的 Application_Start()方法中添加一个部分

  protected void Application_Start(){

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

//强制数据库对模型更改的初始化。
using(var context = new MyContext()){
context.Database.Initialize(force:true);
}
}

您还可以使用自定义初始化程序:

  public class MyDbInit:DropCreateDatabaseAlways< MyContext> 
{

}

然后使用

  Database.SetInitializer(new MyDbInit()); 

更新2



创建一个名为 DeleteDBOnEveryRequest 的新的空MVC4应用程序。
将以下内容放在Global.asax Application_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>());

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

创建一个名为 DatabaseController 有两个动作。



访问操作中,删除数据库并重定向到已处理操作你创建一个数据库,因为它被删除。

 命名空间DeleteDBOnEveryRequest.Controllers 
{
public class DatabaseController控制器
{
public ActionResult Access()
{
using(var context = new BlogContext())
{
context.Database.Delete( );
}
return RedirectToAction(Recreated);
}

public ActionResult Recreated()
{
using(var context = new BlogContext())
{
context.Database。初始化(强制:真);
}
return View();
}
}
}

这是你想要的吗?


Sometimes, I'll delete my development database and run my EF code-first application. I'll get the error:

Cannot open database "AssessmentSystem" requested by the login. The login failed. Login failed for user 'AssessmentAdmin'.

I think this is because the DbContext only runs the DB initialization logic "once per AppDomain when the context is used for the first time", as this page says. This means I need to recycle the IIS application pool to get EF to recreate my database if I drop it.

Is there any way I can get the DB initialization code to run every time I try to access the database? So, it will always check to see whether the DB exists and if not, create it instead of trying to open it, even if it's using the same AppDomain that previously accessed the database that I have now dropped?

Note that I would like this initializtion check to be done on every query, so even having it done in Application_Start isn't often enough; ideally, I'd like to be able to load some DB data, delete the DB, then load some DB data and it would recreate the DB without my even having to restart the application (basically I would just have to reload the web page that loads some DB data).

解决方案

Initializer is executed when you need to access the database so if you want to create database on app start use anything of the following:

    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 An implementation of IDatabaseInitializer that will recreate and optionally re-seed the database with data only if the database does not exist. To seed the database, create a derived class and override the Seed method.

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

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

DropCreateDatabaseIfModelChanges An implementation of IDatabaseInitializerthat will delete, recreate, and optionally re-seed the database with data only if the model has changed since the database was created. This is achieved by writing a hash of the store model to the database when it is created and then comparing that hash with one generated from the current model. To seed the database, create a derived class and override the Seed method.

The initialization strategy can optionally check for database existence, create a new database, and seed the database with data. The default strategy is an instance of CreateDatabaseIfNotExists.

Database.SetInitializer(new DropCreateDatabaseIfModelChanges());

Note that this assumes you have permission to even drop your database.

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

DropCreateDatabaseAlways

An implementation of IDatabaseInitializer that will always recreate and optionally re-seed the database with data the first time that a context is used in the application domain. To seed the database, create a derived class and override the Seed method.

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

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

I recommend that you look at Migrations if you want to track, revert the changes you made to your DB to the previous state http://msdn.microsoft.com/hr-hr/data/jj591621 .

UPDATE

context.Database.Initialize(true);

If the parameter force is set to true, then the initializer is run regardless of whether or not it has been run before. This can be useful if a database is deleted while an app is running and needs to be reinitialized.

For MVC application add a section to the Application_Start() method in the Global.asax

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);
     }    
}

Also you can use a custom initializer :

public class MyDbInit : DropCreateDatabaseAlways<MyContext>
{

}

and then use

Database.SetInitializer(new MyDbInit());

UPDATE 2

Make a new empty MVC4 application called DeleteDBOnEveryRequest. Put the following in the Global.asax Application_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);
            }    
        }

Make a new controller called DatabaseController with two actions.

In the Access action you delete the DB and redirect to Recreated action from where you create a DB as it was previousy deleted.

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();
        }
    }
}

Is this what you wanted?

这篇关于强制代码优先始终初始化不存在的数据库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆