【问题标题】:Why Add-Migration suddenly generates a non empty code migration?为什么 Add-Migration 会突然生成非空代码迁移?
【发布时间】:2016-09-21 16:10:22
【问题描述】:

使用基于 EF6 代码

我的实际实体没有改变,但添加了一个新的 DBSet 以允许直接查询导航属性。

如果我运行 Add-Migration,它会生成一个非空迁移,只为外键重命名一个奇怪的列。

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; }
}

【问题讨论】:

  • 能否也请您添加 ConfigurationPropertyBase 的代码。还给定的名称包含单词 Base 我会问您的模型中是否有 this 的派生类已更改。
  • 其实我发现了一个变化。我编辑了这个问题。它不在模型类中,而是在 DbContext 中。问题仍然存在。为什么会产生这样的迁移?
  • EF 生成在数据库中存储关系所需的列,然后在您使用 POCO 时在 DbContext 内静默管理它们。因为您需要有某种方式来关联两个实体,所以 EF 将使用父实体的 PK 来定义子实体上的隐式外键。我会更新我的答案以匹配。

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


【解决方案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 应该会看到你的权利。

【讨论】:

    猜你喜欢
    • 2023-03-09
    • 2014-12-01
    • 1970-01-01
    • 2013-10-08
    • 2021-12-29
    • 2017-04-03
    • 2019-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多