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

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

问题描述

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

<块引用>

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

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

有什么办法可以让数据库初始化代码在每次我尝试访问数据库时运行?因此,它会始终检查数据库是否存在,如果不存在,则创建它而不是尝试打开它,即使它使用的是以前访问我现在删除的数据库的同一个 AppDomain?

请注意,我希望对每个查询都执行此初始化检查,因此即使在 Application_Start 中完成它通常也不够;理想情况下,我希望能够加载一些数据库数据,删除数据库,然后加载一些数据库数据,它甚至无需重新启动应用程序就可以重新创建数据库(基本上我只需要重新加载网页加载一些数据库数据).

解决方案

Initializer 在您需要访问数据库时执行,因此如果您想在应用程序启动时创建数据库,请使用以下任何内容:

 context.Database.Initialize(true);//如果设置为 true 初始化程序会运行,即使它已经运行.上下文.数据库.创建()

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

CreateDatabaseIfNotExistsIDatabaseInitializer 的一个实现,仅当数据库不存在时,它才会重新创建和可选地重新植入数据库的数据.要为数据库设定种子,请创建一个派生类并覆盖 Seed 方法.

Database.SetInitializer(new CreateDatabaseIfNotExists());

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

DropCreateDatabaseIfModelChangesIDatabaseInitializer 的一个实现,只有在模型自创建数据库后发生更改时,它才会删除、重新创建和可选地用数据重新播种数据库.这是通过在创建商店模型时将其散列写入数据库,然后将该散列与从当前模型生成的散列进行比较来实现的.要为数据库设定种子,请创建一个派生类并覆盖 Seed 方法.

<块引用>

初始化策略可以选择检查数据库存在,创建一个新的数据库,并用数据为数据库做种子.这默认策略是一个实例CreateDatabaseIfNotExists.

Database.SetInitializer(new DropCreateDatabaseIfModelChanges());

<块引用>

请注意,这假设您有权删除数据库.

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

DropCreateDatabaseAlways

IDatabaseInitializer 的一个实现,它总是会在第一次在应用程序域中使用上下文时重新创建和可选地重新植入数据库的数据.要为数据库设定种子,请创建一个派生类并覆盖 Seed 方法.

Database.SetInitializer(new DropCreateDatabaseAlways());

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

我建议您查看迁移,如果您想跟踪,请将您对数据库所做的更改恢复到以前的状态http://msdn.microsoft.com/hr-hr/data/jj591621 .

更新

context.Database.Initialize(true);

<块引用>

如果参数 force 设置为 true,则运行初始化程序不管之前是否运行过.这可以如果在应用程序运行时删除数据库并且需要删除数据库,则很有用重新初始化.

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

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

protected void Application_Start() {Database.SetInitializer(new DropCreateDatabaseAlways());//在模型更改时强制初始化数据库.使用 (var context= new MyContext()) {context.Database.Initialize(force: true);}}

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

公共类 MyDbInit : DropCreateDatabaseAlways{}

然后使用

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(new DropCreateDatabaseAlways());使用 (var context = new BlogContext()){context.Database.Initialize(force: true);}}

使用两个操作创建一个名为 DatabaseController 的新控制器.

访问 操作中,您删除数据库并重定向到 重新创建 操作,从那里创建数据库,因为它先前已被删除.

命名空间 DeleteDBOnEveryRequest.Controllers{公共类 DatabaseController : 控制器{公共 ActionResult 访问(){使用 (var context = new BlogContext()){context.Database.Delete();}return RedirectToAction("重新创建");}公共 ActionResult 重新创建(){使用 (var context = new BlogContext()){context.Database.Initialize(force: true);}返回视图();}}}

这是你想要的吗?

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天全站免登陆