将EF5.x升级到EF6.1.3,奇怪的迁移更改

时间:2017-06-22 14:47:59

标签: entity-framework entity-framework-6 entity-framework-5 ef-migrations

我有一个现有的EF5项目,我升级到EF6.1.3。如果我在EF5上进行“添加 - 迁移”,我会按预期进行空迁移,但在升级到EF6和“添加迁移”后,我得到了一些奇怪的更改。唯一一致的是,有一个多对多的表,以前没有在EF /迁移中定义,它似乎是一个过去开发人工创建它,现在它看起来像EF6找到它并决定承认它通过尝试重命名表,我不知道为什么。这是它想要执行的奇怪改变

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'.

我搜索了整个解决方案,并且在代码库中的任何地方都没有引用错误的表名/对象,DB也没有被更改(因为我注释掉了代码)。我怎么能解决这个错误,因为有些内容是硬编码的,但它不在任何地方的任何.cs文件中?出于绝望,我甚至将重命名添加到我的迁移中,然后在它之后重命名,但仍然会出错。修复异常的唯一方法是让重命名执行,这是我绝对不想要的,因为它违反了我们的命名约定,而且这个代码库已经生产多年,并且这不是一个可接受的更改。

1 个答案:

答案 0 :(得分:1)

在代码中未明确定义配置时,似乎您的问题来自EF6应用与EF5不同的约定。因此,您可以尝试明确定义这些配置。您可以在OnModelCreating课程的DbContext方法中执行此操作。

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,您可以应用在EntityTypeConfiguration类中定义的所有配置。您还可以定义一些明确的约定,并将其应用于Conventions.LoadFromAssembly

EF6映射和约定非常强大。在msdn中,您可以找到有关configurationsconventions的详细信息。