强制代码优先始终初始化不存在的数据库?

时间:2012-10-04 09:33:08

标签: sql-server-2008 entity-framework ado.net ef-code-first

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

  

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

我认为这是因为DbContext仅在第一次使用上下文时“每个AppDomain运行一次数据库初始化逻辑”,如this page所述。这意味着我需要回收IIS应用程序池,以便在我删除它时重新创建我的数据库。

我是否有办法让每次运行的数据库初始化代码我尝试访问数据库?因此,它将始终检查数据库是否存在,如果不存在,则创建它而不是尝试打开它,即使它使用的是先前访问过我已经删除的数据库的相同AppDomain吗?

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

1 个答案:

答案 0 :(得分:35)

当您需要访问数据库时执行

初始化程序,因此如果您想在应用程序启动时创建数据库,请使用以下任何内容:

    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 IDatabaseInitializert的实现,仅当模型自创建数据库以来已更改时,才会删除,重新创建数据库并使用数据重新种子化。这是通过在创建数据库时将存储模型的哈希值写入数据库,然后将该哈希值与当前模型生成的哈希值进行比较来实现的。要为数据库设定种子,请创建派生类并覆盖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

如果您想要跟踪,建议您查看迁移,将您对数据库所做的更改还原为之前的状态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<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());

更新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>());    

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

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

访问操作中,您删除数据库并重定向到重新创建操作,您可以在此处创建数据库,因为之前删除了该数据库。

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

这是你想要的吗?