0

我有一個現有的EF5項目,我升級到EF6.1.3。如果我在EF5上執行「添加遷移」,我會像預期的那樣得到空遷移,但在升級到EF6和「添加遷移」之後,我收到了一些奇怪的更改。唯一一致的是,有一個多對多的表格在EF/migrations中沒有定義過,它似乎是一個過去的開發者手動創建的,現在看起來像EF6發現它並決定承認它通過嘗試重命名錶,我不知道爲什麼。這是它要執行EF5.x升級到EF6.1.3,奇怪的遷移變化

RenameTable(name: "dbo.DashboardUserDashboards", newName: "DashboardDashboardUsers"); 
RenameTable(name: "dbo.DashboardOrganizationAdjunctDashboardProcesses", newName: "DashboardProcessDashboardOrganizationAdjuncts"); 
RenameColumn(table: "dbo.DashboardProcessTaskTriggers", name: "DaysOfWeek", newName: "__mig_tmp__0"); 
RenameColumn(table: "dbo.DashboardProcessTaskTriggers", name: "DaysOfWeek1", newName: "DaysOfWeek"); 
RenameColumn(table: "dbo.DashboardProcessTaskTriggers", name: "__mig_tmp__0", newName: "DaysOfWeek1"); 

我從來沒有遇到這些奇怪的變化,並且它的代碼運行正常,我添加了一個新的遷移,這是空的,在這裏我添加了一個不相關的存儲過程,這也運行得很好&代碼執行。但現在當我運行的代碼庫,我得到

Invalid object name 'dbo.DashboardDashboardUsers'. 
Exception Details: System.Data.SqlClient.SqlException: Invalid object name 'dbo.DashboardDashboardUsers'. 

我找遍了整個解決方案和壞表名/對象從來沒有在代碼庫中的任何地方引用,也沒有數據庫被改變的異常(如我註釋掉碼)。我怎樣才能解決這個錯誤,因爲它是硬編碼的,但它不在任何.cs文件中?絕望之餘,我甚至將重命名添加到我的遷移中,然後將它重新命名,但仍然出現錯誤。修復這個異常的唯一方法就是讓重命名執行,我絕對不想這樣做,因爲它違反了我們的命名約定,而且這個代碼庫已經投入使用多年了,這不是一個可以接受的改變。

回答

1

看起來你的問題來自EF6應用不同於EF5的慣例,當配置沒有在代碼中明確定義。所以你可以嘗試明確定義這些配置。您可以在DbContext課程的OnModelCreating方法中執行此操作。

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    base.OnModelCreating(modelBuilder); 
    ... 
    <your configurations here> 
} 

我能想到的幾件事情要嘗試:

  • 集的模式明確:

    modelBuilder.HasDefaultSchema("dbo"); 
    

    看起來你的架構名稱是dbo。請注意,在您的RenameTable句子中,表名稱不同,但舊名稱中包含模式前綴,但新名稱不包含。

  • 配置映射的許多一對多的關係:

    modelBuilder.Entity<User>() 
        .HasMany(x => x.Dashboards) 
        .WithMany(x => x.Users) 
        .Map(x => { 
         x.MapRightKey("UserId"); 
         x.MapLeftKey("DashboardId"); 
         x.ToTable("DashboardUserDashboards"); 
        }); 
    

    這裏的關鍵部分是.ToTable("DashboardUserDashboards")配置,明確將表物理名稱。對於其他配置,我對您的模型類做了一些假設,因爲您沒有顯示該代碼,例如您有導航屬性User.DashboardsDashboard.Users。也許你沒有這些導航屬性,因爲你不需要它們。您必須將該代碼適用於特定的模型類。

如果你有很多的EF配置代碼,最好是使用一個映射類爲每個實體,這是你的模型類的類型參數擴展EntityTypeConfiguration類:

public class UserMap : EntityTypeConfiguration<User> 
{ 
    public Map() 
    { 
     HasMany(x => x.Dashboards) 
      ... 
    } 
} 

這是典型的OnModelCreating方法:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    base.OnModelCreating(modelBuilder); 

    modelBuilder.HasDefaultSchema("auth"); 
    var assembly = Assembly.GetExecutingAssembly(); 
    modelBuilder.Configurations.AddFromAssembly(assembly); 
    modelBuilder.Conventions.AddFromAssembly(assembly); 
} 

使用Configurations.LoadFromAssembly你申請你在EntityTypeConfiguratio中定義的所有配置n班。您也可以定義一些明確的約定,並將其應用於Conventions.LoadFromAssembly

EF6映射和約定非常強大。在msdn中,你可以找到有關configurationsconventions的詳細信息。

+0

謝謝,我一直在檢查你的建議,他們正在幫助,一次一點。我的下一個問題是,爲什麼EF會刪除,然後重新創建索引,在過去的遷移中已經有該列索引的表上。 – TravisO

+1

如果遷移代碼沒有顯示有關爲什麼重新創建索引的任何提示,則可以嘗試查看由EF生成的SQL:使用參數「-Scr​​ipt」運行「Update-Database」。這將生成SQL而不執行遷移。查看新索引中的更改:名稱,模式,列順序。在你的代碼中爲它設置一個明確的配置。 – Diana