2013-02-09 23 views
3

我目前正在開發具有版本1用戶的現有代碼庫的應用程序的第2版,但我也需要將新版本新用戶(即乾淨安裝)。版本1使用實體框架4.1。版本2使用實體框架5.將Entity Framework 4.1數據庫遷移到EF5進行升級,爲新安裝創建新數據庫

我的問題是我需要能夠升級現有的版本1用戶到版本2並將他們的數據庫遷移到新版本的模式。新的模式添加了許多新表格,保留了現有的幾個表格,並刪除了其他表格。

我在旅途中發現EF4.1不包含_MigrationHistory表。所以,我回到了我原來的版本1的代碼,它升級到EF5和運行如下的初始遷移:

Add-Migration Initial -IgnoreChanges 

這很好地工作,以獲得原始版本1(EF4.1)數據庫準備遷移(即添加_MigrationHistory表)。然後我口這個交給我的版本2的代碼並運行:

Update-Database 

它創建_MigrationHistory表,然後我運行:

Add-Migration Version2 

生成的數據庫的一個很好的遷移最多2版本。

這工作完全如果數據庫在任一版本1架構或版本2架構(無遷移在後者的情況下施加的),爲我使用以下初始化劑已經存在:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, Configuration>()); 

但是,如果數據庫不存在,Initial移植成功運行,但Version2遷移失敗,因爲一些遷移步驟下降顯然不能在一個空數據庫中的表,索引和外鍵。

因此,我完全處於虧損狀態 - 如何將現有的1版用戶遷移到版本2(並保留其數據),還支持需要全新創建數據庫的新安裝?

我見過很多關於創建和運行SQL腳本遷移的想法,但我真的需要在啓動我的應用程序時自動完成此操作。最終用戶應該只需要運行MSI文件即可升級。

UPDATE:這是由w.brian(抱歉,我不能贊成票尚)以下建議的解決方案:

string connectionString = ConfigurationManager.ConnectionStrings["DbContext"].ConnectionString; 
if (Database.Exists(connectionString)) 
{ 
    Database.SetInitializer(new MigrateDatabaseToLatestVersion<DbContext, Migrations.Configuration>()); 
} 
else 
{ 
    Database.SetInitializer(new DefaultDataInitialiser()); 
} 

UPDATE2:以上似乎是通過工作的第一次一個新的創造。但是,下一次運行通過Database.Exists()檢查並嘗試遷移數據庫。但是,由於_MigrationHistory表中只有一個條目(由new/clean安裝生成),並且遷移有兩個條目(一個用於EF4.1遷移;一個用於新模式),遷移邏輯從開始並嘗試應用每個遷移。

這會失敗,因爲它會嘗試創建已存在於數據庫中的表 - 它將它們創建爲乾淨安裝的一部分!

所以問題的關鍵是,這種方法混淆了遷移邏輯。

UPDATE3:所以我想我已經想出瞭如何創建初始數據庫並允許後續運行只應用遷移。從上面看,如果數據庫已經存在,繼續使用遷移代碼。

如果數據庫不存在,使用DefaultDataInitialiser並在Seed()方法,執行以下操作:

context.Database.ExecuteSqlCommand(@"DELETE FROM [__MigrationHistory]"); 

byte[] version1Model = ConvertHexStringToByteArray("1F8B..."); 
context.Database.ExecuteSqlCommand(@"INSERT INTO [__MigrationHistory] 
             ([MigrationId] 
             ,[Model] 
             ,[ProductVersion]) 
            VALUES 
             ('201302082120145_Initial' 
             ,{0} 
             ,'5.0.0.net40')", new object[] { version1Model }); 

byte[] version2Model = ConvertHexStringToByteArray("1F8B..."); 
context.Database.ExecuteSqlCommand(@"INSERT INTO [__MigrationHistory] 
             ([MigrationId] 
             ,[Model] 
             ,[ProductVersion]) 
            VALUES 
             ('201302082200350_Version-2' 
             ,{0} 
             ,'5.0.0.net40')", version2Model); 

這得到但從遷移邏輯的角度來看,新的數據庫「完全遷移」。下一次應用程序運行時,數據庫存在並運行,看到數據庫處於最新版本(或將來升級到下一個遷移)並且很高興。

不幸的是,將來需要將每個新的遷移添加到這個Seed()方法中,以便從頭開始創建數據庫。

我在哪裏得到用於模型的十六進制字符串?我從SQL Server Management Studio中從數據庫的遷移版本複製它。

回答

1

我只會在升級時使用MigrateDatabaseToLatestVersion初始值設定項,而不是在新安裝時使用。這將要求您直接查詢SQL Server以查看數據庫是否存在,但我認爲這不應該太困難,因爲您可以訪問連接字符串。

+0

我應該測試數據庫是否存在使用'Database.Exists(string connectionString)'?如果是這樣,我如何從'App.config'獲得最合適的連接字符串?我只有一個,但如果有多個呢? – blowfly 2013-02-09 22:24:47

+0

更新:剛剛查找了'ConfigurationManager.ConnectionStrings [「name」]。ConnectionString;' – blowfly 2013-02-09 22:30:34

+0

是的,我認爲通過它的名字獲取連接字符串是一種方式。 – 2013-02-09 22:32:24

相關問題