24

我創建了一個新的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

你有沒有想過這個想法? – Eonasdan

+0

@Eonasdan,一年後,是的。請看我的答案。 – joelmdev

回答

0

您必須停止IISExpress實例並重新啓動它(通過在Visual Studio中按F5鍵)。然後您將能夠再次創建數據庫。

2

您可以處理的Code First數據庫初始化在Global.asax文件的Application_Start方法中在項目的根文件夾,如下所示:

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

如果你傳遞null SetInitializer它不會創造或修改你的數據庫表,你應該手動完成。

數據庫不重新生成的原因是Application_Start在應用程序生命週期中僅觸發一次。

+1

這不再是MVC4中的最佳做法。改爲使用App_Start文件夾中的類。 – kingdango

2

MVC生成的代碼使用名爲「DefaultConnection」的數據庫連接字符串。 如果您在Web.config中使用不同的名稱,你需要參考該名:

  1. InitializeSimpleMembershipAttribute.SimpleMembershipInitializer.ctor()在InitializeSimpleMembershipAttribute.cs)。
  2. UsersContext.ctor()在AccountModel.cs

(或只是在你的項目中搜索 「DefaultConnection」)。

1

只有通過SQL管理工具或對象資源管理器,才能刪除資源管理器中自動創建的.mdf文件。

你得到(並可以在您所提供的步驟複製)的問題是該數據庫中的LocalDB仍註冊。

+0

LocalDB支持數據庫爲文件,所以這不一定是真的。請參閱http://blogs.msdn.com/b/sqlexpress/archive/2011/07/12/introducing-localdb-a-better-sql-express.aspx – joelmdev

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標誌,如果是假的它初始化裁判瞄準它的過去,在這種情況下SimpleMembershipInitializer類型的_initializer。此時它將標誌設置爲真,然後繼續。如果LazyInitializer.EnsureInitialized看到該標誌是真的,它什麼也不做,只是返回目標。由於該標誌是一個靜態變量,因此它在應用程序的整個生命週期中保持其值,這意味着在第一次初始化函數EnsureInitialized之後,即使數據庫文件不再存在,它也會始終簡單地返回目標。換句話說,如果在初始化後刪除.mdf文件,則應用程序不會知道,並且應用程序試圖從數據庫讀取或寫入時會拋出異常。爲了解決這個問題,你必須重新啓動應用程序,這意味着殺死開發服務器,如果這是你正在使用或在IIS中重新啓動應用程序。

所以這就是你面臨的問題,但我懷疑很多跑過這個問題的人都有一個類似但不同的問題,他們在嘗試登錄時收到與此類似的錯誤消息:

CREATE FILE在嘗試打開或創建物理文件'C:\ path \ to \ your \ project \ App_Data \ dbfile.mdf'時遇到操作系統錯誤5(訪問被拒絕)。 CREATE DATABASE失敗。列出的某些文件名不能被創建。檢查相關的錯誤。

這很容易解決,我會盡快在這裏介紹。

默認狀態下的Visual Studio 2012使用的SQL Server Express的削減版本叫的LocalDB。 LocalDB將啓動應用程序的子進程,如果您在Visual Studio的開發服務器上運行應用程序(例如,http:// localhost:[port]是您的瀏覽器中顯示的內容),那麼您正在運行應用程序和您的用戶帳戶下的LocalDB,而不是在SYSTEM或NETWORKSERVICE下。您需要做的所有事情就是爲您的用戶分配項目的App_Data文件夾的修改權限。再次嘗試登錄,應該成功創建.mdf文件。

如果你好奇,你可以瞭解更多有關的LocalDB here.

+0

修改App_Data文件夾的權限解決了我的問題。我希望這可以幫助別人。 – BrianLegg

9

得到了同樣的問題,發現我的解決方案here。 所有你需要做的就是通過打開VS開發人員命令提示符停止的LocalDB並輸入(不帶引號):

「sqllocaldb.exe停止V11.0」

「sqllocaldb.exe刪除V11。0"

下一次EF將重新生成文件以及數據庫。

+0

您的鏈接幫助了我:) –

+2

LocalDB實例可能有其他名稱。運行'sqllocaldb info'將列出所有現有的LocalDB實例。 – Paul

0

什麼固定它對於我來說,當我收到這個錯誤是我在VS項目的App.config文件改變了連接字符串。

我已經在連接字符串中添加了這個:

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

希望這有助於別人

012。
相關問題