1

我在Visual Studio 2015中使用Code-First進行數據庫遷移。一路上,我完成了遷移步驟直到添加遷移。使用Code-First更新數據庫時出錯:「數據庫中已有一個名爲'something'的對象。」

附加遷移後,我已經添加了這行代碼

Database.SetInitializer(New MigrateDatabaseToLatestVersion(Of DbContext1, Migrations.Configuration)) 

在我的DbContext構造函數來設置數據庫初始化程序,因爲我以前錯過了這一步。之後,我執行

"Add-Migration initial -Force" 

在包管理器控制檯中,因爲我擔心這部分是在添加遷移過程中需要的。於是,我直接執行

"Update-Database" 

問題是我這樣做後,錯誤出來

此操作需要在「主」數據庫的連接。無法創建與「主」數據庫的連接,因爲原始數據庫連接已打開且憑據已從連接字符串中刪除。提供未打開的連接。

ADDED

之後我重新啓動我的電腦,上面的錯誤不出來了,當我執行「更新-數據庫」。相反,另一個錯誤出來了:

數據庫中已經有一個名爲'something'的對象。

我看到一個答案線程建議執行

Add-Migration Initial -IgnoreChanges 

其次

Update-Database -verbose 

我都試過,但它仍然顯示了同樣的錯誤。

回答

6

爲了能夠解決您的問題,您應該瞭解EF如何處理連接字符串以及遷移如何工作。

如何EF涉及連接字符串:通常你DbContext有一個參數的構造函數,調用其基類的構造函數有硬編碼的連接字符串名稱。您的項目app.configweb.config文件應包含一個connectionStrings部分,該部分定義具有該名稱的連接字符串。 這是您在項目中使用的默認連接字符串,如果您未明確向Package Manager Console命令提供連接字符串參數。

與連接字符串名稱MyConnectionStringName一些示例代碼:

public class MyDbContext : DbContext 
{ 
    public MyDbContext() : base("MyConnectionStringName") { ... } 
    ... 
} 

而在你.config文件:

<configuration> 
    ... 
    <connectionStrings> 
    <add name="MyConnectionStringName" connectionString="..." /> 
    </connectionStrings> 
</configuration> 

如果不使用這種方法,你仍然可以手動提供正確的連接字符串作爲在包管理器控制檯中的參數,如下所示:

Update-Database -ConnectionString <your connection string here> -ConnectionProviderName System.Data.SqlClient 

您也可以使用您在.config文件中定義的任何連接字符串名稱:

Update-Database -ConnectionStringName MyConnectionStringName 

現在大概遷移如何工作:遷移是代碼文件。每次運行Add-Migration時,都會生成/更新代碼文件,通常位於項目內部名爲Migrations的文件夾中。遷移文件的名稱由其生成時間戳與運行Add-Migration時使用的名稱拼接而成。您可以檢查這些文件的內容並查看運行Add-Migration的效果。您也可以在生成後修改它們,並添加自己的代碼,儘管您暫時不需要這樣做。

遷移旨在是增量式的。您從Initial遷移開始,每次更改模型代碼時都會生成新的遷移文件。該數據庫包含一個名爲__MigrationsHistory的表,可以跟蹤在數據庫中運行過哪些遷移。

每一次遷移都有一個方法Up和一個方法Down。當您運行Update-Database時,總是有兩個隱式參數:SourceMigrationTargetMigration。 EF逐步應用SourceMigrationTargetMigration之間的所有遷移的Up方法(如果要降級數據庫,則使用Down方法)。當您未指定SourceMigrationTargetMigration參數時的默認方案是SourceMigration是應用於數據庫的最後一次遷移,而TargetMigration是最後一個掛起的遷移。 EF通過查詢項目的默認數據庫的__MigrationsHistory表來確定這些參數,因此如果該數據庫不在一致的狀態,則可能會錯誤地生成遷移。我認爲這是造成你的問題的原因。

所以每次運行Update-Database EF時間眺望__MigrationsHistory表知道哪些遷移必須運行,這取決於你的數據庫的狀態,並執行新的記錄被插入在該表中的每個遷移的SQL後應用遷移。

看來,在某些時候你的數據庫__MigrationsHistory內容搞砸了。發生在運行Update-DatabaseAdd-Migrations而沒有按照正確的順序和使用-force參數。

我的建議,以解決您的問題:從頭開始:刪除數據庫,刪除遷移文件,生成Add-Migration Initial一個新的清潔Initial遷移,運行它只有Update-Database一次。從這一點開始,每次更改模型代碼時,都會生成一個新的增量遷移,其中包含Add Migration YourNewMigrationName,每次使用不同的名稱,並通過運行Update-Database一次應用新的遷移。

注意:如果您對遷移的工作方式有足夠的瞭解,您可以只使用一個Initial遷移,並在模型代碼發生更改時通過執行Add-Migrations Initial -force來更新它,而不是增量遷移。 -force參數確保不會生成新的遷移文件,而是會覆蓋現有的Initial遷移文件。這種方法在開發階段很方便,但在生產中通常不是一種好方法,因爲您可能希望在每次部署新版本代碼時增量運行數據庫更新(您可能無法刪除數據庫並重新創建它,並且還需要維護數據,並確保在更新數據庫時不會丟失數據)。

遷移是由EF生成的用於創建和更新數據庫的代碼文件。當您運行Update-Database時,遷移將轉換爲針對您的數據庫執行的SQL。如果您想查看針對特定遷移生成的確切SQL,您可以運行Update-Database -Script -SourceMigration SomeMigration -TargetMigration SomeOtherMigration。此命令不會修改數據庫,只會生成並顯示將在實際Update-Database執行中應用的SQL。

有關生成和運行遷移的更多信息,請參閱here

祝你好運!

+0

非常感謝您的見解。我沒有刪除我的數據庫。我嘗試從Migrations文件夾中刪除「初始」文件,而不是整個文件夾。然後我做了'添加遷移初始'和'更新數據庫'。它現在工作! – Nurul

+0

不客氣! – Diana

+0

對不起,但我有關於Code-first的問題。你可以請看看它[這裏](http://stackoverflow.com/questions/42048555/is-there-any-way-i-can-just-create-a-table-in-sql-server-和 - 然後更新-Mag)爲我? – Nurul

相關問題