为什么Add-Migration会突然生成非空代码迁移?

时间:2016-09-20 14:55:33

标签: c# entity-framework entity-framework-6

使用基于EF6代码的

我的实际实体尚未更改,但添加了新的DBSet以允许直接查询导航属性。

如果我运行添加迁移,它会生成一个非空迁移,只对外键进行奇怪的列重命名。

public override void Up()
{
    RenameColumn(table: "dbo.ConfigurationPropertyBases", name: "ConfigurationClass_Id", newName: "ConfigurationClass_Id1");
    RenameIndex(table: "dbo.ConfigurationPropertyBases", name: "IX_ConfigurationClass_Id", newName: "IX_ConfigurationClass_Id1");
}

为什么会产生类似的迁移?

DbContext中的更改:

public class ConfigurationContext : DbContext
{
   //(...)

    public DbSet<ConfigurationPackage> Packages { get; set; }
    public DbSet<ConfigurationPropertyBase> ConfigurationPropertyBases { get; set; }

    // THIS WAS ADDED
    public DbSet<ConfigurationClass> ConfigurationClass { get; set; }
}

db模型:(我只显示相关的导航属性)。

public class ConfigurationPackage
{
    public int Id { get; set; }
    //(...)
    public List<ConfigurationClass> Configurations { get; set; }
}

public class ConfigurationClass
{
    public int Id { get; set; }

    public List<ConfigurationPropertyBase> ConfigurationProperties { get; set; }
}

public abstract class ConfigurationPropertyBase
{
    public int Id { get; set; }
    public string Name { get; set; }
    //(no navigation propeties here)
}

我有许多继承自ConfigurationPropertyBase的类,但它们都只包含简单的属性,如int或string(没有导航属性),除了以下属性:

public class ConfigurationPropertyComplex : ConfigurationPropertyBase
{
    public ConfigurationClass ConfigurationClass { get; set; }
}

1 个答案:

答案 0 :(得分:1)

实体框架约定将创建一个列来保存未在模型中明确定义的关系信息。 在msdn documentation中声明:

  

除了导航属性之外,我们还建议您在表示依赖对象的类型上包含外键属性。与主要主键属性具有相同数据类型且名称遵循以下格式之一的任何属性表示关系的外键

考虑到这一点,您可能没有在脑海中更改模型,但可能在另一个类中,您已使用隐式外键更改了导航属性。此外,根据您是否派生了ConfigurationPropertyBase类,这些更改将影响模型。

在任何情况下,遵循建议明确定义您的外键属性,生活变得更加容易。 另请更新您的问题,以包括ConfigurationPropertyBase类及其衍生产品中的一个或两个。

编辑以回应更新的问题

正如您所发现的那样,变化是在上下文中。当您将ConfigurationClass添加到上下文时,它必须重新排列其隐式外键。

再次引用documentation

  

当外键列未包含在模型中时,关联信息作为独立对象进行管理。通过对象引用而不是外键属性来跟踪关系。这种类型的关联称为独立关联。修改独立关联的最常用方法是修改为参与关联的每个实体生成的导航属性。

明确地接受建议并管理外键属性,以便EF不会决定看起来没有意义的更改。 例如:

public class ConfigurationPackage
{
    public int Id { get; set; }
    //(...)
    [InverseProperty("ConfigurationPackage")]
    public List<ConfigurationClass> Configurations { get; set; }
}

public class ConfigurationClass
{
    public int Id { get; set; }
    [ForeignKey("ConfigurationPackage")]
    public int ConfigurationPackageId { get; set; }
    public ConfigurationPackage ConfigurationPackage { get; set; }
    [InverseProperty("ConfigurationClass")]
    public List<ConfigurationPropertyBase> ConfigurationProperties { get; set; }
}

public abstract class ConfigurationPropertyBase
{
    public int Id { get; set; }
    public string Name { get; set; }
    //(no navigation propeties here)
    [ForeignKey("ConfigurationClass")]
    public int ConfigurationClassId { get; set; }
    public ConfigurationClass ConfigurationClass { get; set; }
}

是的,这是一项更多的工作和更多的学习,但EF将完全按照你的说法完成。关于数据注释的更多documentation应该会看到你正确的。