代码首次尝试创建数据库时出现异常

时间:2012-08-30 20:42:49

标签: c# asp.net-mvc entity-framework entity-framework-4 ef-code-first

我已经创建了一个新的ASP.NET MVC 4应用程序,并希望它首先使用代码。但是,如果数据库文件不存在,它似乎最初不会创建数据库文件。如果我从App_Data文件夹中删除.mdf文件,那么当应用程序尝试访问数据库时,我会收到以下异常:

System.Data.SqlClient.SqlException: Cannot attach the file '<path-to-db-file>.mdf' as database '<my-db-file-name>'.

如果我在调试器中的应用程序中运行它,那么我可以看到在调用LazyInitializer.EnsureInitialized时InitializeSimpleMembershipAttribute :: OnActionExecuting方法中发生异常。被捕获的例外是:

[System.Reflection.TargetInvocationException]   {"Exception has been thrown by the target of an invocation."}   System.Reflection.TargetInvocationException

内部例外:

[System.InvalidOperationException]  {"The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588"} System.InvalidOperationException

然后我将上面提到的第一个例外作为内部例外。

任何想法我做错了什么?

更新

我刚刚尝试使用全新的MVC4应用程序。我可以通过执行以下操作来复制它:

  1. 在VS向导中创建MVC应用程序。
  2. 首次运行应用程序并转到登录页面(注意现在生成mdf文件)。
  3. 删除mdf文件,然后返回登录页面。现在抛出异常。

7 个答案:

答案 0 :(得分:9)

遇到同样的问题,找到了我的解决方案here。 所有你需要做的就是通过打开VS开发人员命令提示符并输入(不带引号)来停止LocalDb:

“sqllocaldb.exe stop v11.0”

“sqllocaldb.exe delete v11.0”

下次EF将重新生成文件以及db。

答案 1 :(得分:4)

如果深入了解应用程序的InitializeSimpleMembershipAttribute类,您将看到它继承的ActionFilterAttribute类的以下重写方法:

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Ensure ASP.NET Simple Membership is initialized only once per app start
        LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
    }

请注意评论。应用程序每次运行检查一次,以确保简单成员资格已正确初始化。查看类顶部的私有变量:

    private static SimpleMembershipInitializer _initializer;
    private static object _initializerLock = new object();
    private static bool _isInitialized;

它们都是静态的,它们都作为引用传递。对于您的情况,重要的是_isInitialized。 LazyInitializer.EnsureInitialized所做的是检查_isInitialized标志,如果它是false,则初始化它传递的ref目标,在这种情况下是_initializer类型的SimpleMembershipInitializer。此时,它将标志设置为true并继续前进。如果LazyInitializer.EnsureInitialized看到该标志为真,则它只会返回目标。由于该标志是一个静态变量,它在应用程序的生命周期中保持其值,这意味着在第一次初始化之后,即使数据库文件不再存在,EnsureInitialized也将始终只返回目标。换句话说,如果在初始化后删除.mdf文件,则应用程序将不知道,并且当应用程序尝试从数据库读取或写入时将抛出异常。为了解决这个问题,您必须重新启动应用程序,这意味着如果您正在使用该服务器或在IIS中重新启动应用程序,则终止开发服务器。

这就是你所面临的问题,但我怀疑许多人在遇到这个问题时遇到了类似但不同的问题,他们在尝试登录时会收到与此类似的错误消息:

  尝试打开或创建物理文件'C:\ path \ to \ your \ project \ App_Data \ dbfile.mdf'时,

CREATE FILE遇到操作系统错误5(访问被拒绝。)。   CREATE DATABASE失败。无法创建列出的某些文件名。检查相关错误。

这很容易解决,我也会在这里快速解决。

默认情况下,Visual Studio 2012使用称为LocalDB的SQL Server Express的简化版本。 LocalDB将启动应用程序的子进程,如果您在Visual Studio的开发服务器上运行应用程序(例如http:// localhost:[port]显示在浏览器中),那么您正在运行该应用程序您的用户帐户下的LocalDB和LocalDB,而不是SYSTEM或NETWORKSERVICE。要解决此问题,您需要为用户为项目的App_Data文件夹分配修改权限。再次尝试登录,应该成功创建.mdf文件。

如果您感到好奇,可以了解有关LocalDB here.

的更多信息

答案 2 :(得分:2)

您可以在项目的根文件夹中的Global.asax文件的Application_Start方法中处理Code First数据库初始化,如下所示:

    protected void Application_Start()
    {
        Database.SetInitializer<MyDBContext>(null);
    }

如果将null传递给SetInitializer,它将无法创建或更改数据库表,您应该手动执行。

不重新生成数据库的原因是Application_Start在应用程序生命周期内只被触发一次。

答案 3 :(得分:2)

MVC生成的代码使用名为“DefaultConnection”的数据库连接字符串。 如果在Web.config中使用了其他名称,则需要在以下位置引用此名称:

  1. InitializeSimpleMembershipAttribute.cs中的InitializeSimpleMembershipAttribute.SimpleMembershipInitializer.ctor()。
  2. AccountModel.cs中的UsersContext.ctor()
  3. (或者只是在项目中搜索“DefaultConnection”)。

答案 4 :(得分:1)

您永远不应该在资源管理器中删除自动处理的.mdf文件,只能通过SQL管理工具或对象资源管理器中删除。

您获得的问题(并且可以在您提供的步骤中复制)是数据库仍在LocalDb中注册。

答案 5 :(得分:0)

您必须停止IISExpress实例并再次重新启动它(通过在Visual Studio中按F5)。然后,您将能够再次创建数据库。

答案 6 :(得分:0)

当我收到此错误时为我修复的是我更改了VS Project的App.config文件中的连接字符串。

我在连接字符串中添加了这个:

  <connectionStrings>
<add name="Blog" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Integrated Security=true;AttachDbFileName=C:\Users\kostadin\Database1.mdf" providerName="System.Data.SqlClient" />

希望这有助于其他人。