17

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

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

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

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

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

4

1 回答 1

37

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

    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

如果您想跟踪,我建议您查看迁移,将您对数据库所做的更改恢复到以前的状态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());

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

这是你想要的吗?

于 2012-10-08T09:13:58.030 回答