【问题标题】:Entity Framework The ALTER TABLE statement conflicted with the FOREIGN KEY constraint实体框架 ALTER TABLE 语句与 FOREIGN KEY 约束冲突
【发布时间】:2014-01-19 05:11:28
【问题描述】:

在更新实体框架中的数据库,代码优先迁移时,我收到此错误:

ALTER TABLE 语句与 FOREIGN KEY 约束“FK_dbo.Clients_dbo.MedicalGroups_MedicalGroupId”冲突。冲突发生在数据库“hrbc”、表“dbo.MedicalGroups”、列“Id”中。

这是我的课:

public partial class Client
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int? MedicalGroupId { get; set; }
    [ForeignKey("MedicalGroupId")]
    public virtual MedicalGroups MedicalGroup { get { return _MedicalGroup; } set { _MedicalGroup = value; } }
}

这是我的第二节课:

public partial class MedicalGroups
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}

这是我正在尝试申请的迁移:

public override void Up()
{
    AddForeignKey("dbo.Clients", "MedicalGroupId", "dbo.MedicalGroups", "Id");
    CreateIndex("dbo.Clients", "MedicalGroupId");
}

【问题讨论】:

  • 我认为你需要删除 FK_dbo.Clients_dbo.MedicalGroups_MedicalGroupId
  • 您在这一步之前是否更改了模型,在 Down() 案例中的情况如何?如果你做错了什么,你应该从数据库中删除前索引作为提及@brykneval
  • @brykneval 名称没有问题,因为我确实更改了外键约束的名称但没有帮助!!!
  • @AOZ 是的,我已经在数据库中添加了医疗组表。现在我想在客户和医疗集团之间建立联系。而且down()方法中没有代码
  • @AOZ 假设我做错了什么我怎么知道?

标签: c# sql .net sql-server entity-framework


【解决方案1】:

检查数据库中是否存在与 FK 约束冲突导致创建失败的数据。

【讨论】:

  • 但是MedicalGroupId不是必须的.​​.现有数据应该没有问题
  • @turnkey 是的,我的客户表中已经有数据,但我无法删除它。
  • @AOZ 有什么解决办法吗?
  • 这不是删除数据,而是修复它们。如果有Client 引用不存在的MedicalGroup,您将永远无法添加FK。
  • 在我的情况下,我将外键属性设置为 int 而不是 int?所以 EF 添加了一个默认值 0,它指向外部表中没有条目。
【解决方案2】:

我认为 @Cory 让您接近正确的解决方案,只是您没有花时间进行调查。

在 add-migration 代码中,可能会生成迁移

public override void Up()
{
AddColumn("dbo.ClientContacts", "FamilialRelationshipId", c => c.Int(nullable: false));
CreateIndex("dbo.ClientContacts", "FamilialRelationshipId");
AddForeignKey("dbo.ClientContacts", "FamilialRelationshipId", "dbo.FamilialRelationships",        "FamilialRelationshipId");
}

注意 nullable:false;如果您的模型的 Id 是 int 而不是 int? (nullable int) 迁移代码将 nullable 设置为 false。 您的模型显示您正在使用默认为 0 的不可为空的 int,并且您可能没有值为 0 的外键项。

现在,您必须创建一个存在于外键表中的默认值, 或者如果您使用 SQL Server 创建约束,则不检查创建约束。但请记住这一点:如果您使用 [DefaultValue(0)] 属性装饰您的属性,它不会像 SQL Column Add 那样更改现有数据,如果指定了默认值。

我建议您更改模型类以允许可为空的 int。 然后,在您的种子方法中,针对 dbcontext 创建一个简单的方法,以使用默认值更新新列,因为数据注释中的 [DefaultValue] 属性不会修改您的数据。

Add-Migration / Update-Database 创建列和约束。 接下来,如果您希望允许使用不可为空的 int,请修改您的模型,并假设您再次将所有行更改为外键的某个有效值,即 Add-Migration / Update-database。 这为您的模型迁移提供了一条完整的链。稍后当您发布到实时站点时会派上用场,因为您的数据模型更改流程将保持不变。

  • 希望这会有所帮助。

【讨论】:

  • 我们在这里遇到了两步解决方案的问题。如果必须一次应用多个迁移,您最终会得到以下顺序:创建可为空的字段,使其不可为空,然后运行种子。没有地方可以真正将数据放入 FK 字段,一切都再次爆炸。我找到的唯一两个解决方案是从链接到 FK 的表中删除数据,或者使字段可为空并保持这种状态。
  • @AriRoth +1 但肯定还有另一种方式,这有多普遍?!
【解决方案3】:

这个错误告诉你你违反了外键约束。要解决你有几个解决方案

  1. 修复您的数据 - Clients 表中的某处记录具有 MedicalGroupId,而 MedicalGroups 表。编写查询以找出哪些 ID 没有 存在于MedicalGroups 表中并手动修复数据 自己。
  2. 删除外键约束 - 显然,如果您删除外键约束,您将不再被此消息困扰。不幸的是,数据库将不再强制执行这种关系,并且将来可能会使这个问题变得更糟。
  3. 使用WITH NOCHECK 创建约束 - 您可以使用WITH NOCHECK 选项创建外键约束。此选项告诉 SQL Server 不要将此约束应用于现有数据。 SQL Server 将在以后的任何 INSERTS/UPDATES/DELETES 中检查此约束。

【讨论】:

    【解决方案4】:

    对于可能出现在此处的其他人,如果您使用 Code-First Entity Framework 并且只是尝试将新的必需列添加到包含现有数据的表中,则可能会有一个非常简单的解决方法。

    注意:在您执行此操作之前,只需知道您需要为所有现有行的此新列添加一个有效值。在继续之前,请考虑您将向现有行添加什么值。您可能希望向所需的查找表提供一个指示“无效”或“未知”的值。

    在您的模型中,通过添加?在 int 之后。保存并编译模型。运行更新数据库。

    示例:

    [ForeignKey("Title")]
    public int? TitleId { get; set; }

    在数据库中,通过将 NULL 值替换为有效的查找值来更新表。在我的例子中,我将“未知”添加到我的标题查找表中,然后批量编辑所有行以引用该查找 ID。

    返回您的模型,删除“?”所以该列不再可以为空。保存并编译模型,然后运行 ​​Update-Database

    您现在应该可以开始了。

    【讨论】:

      【解决方案5】:

      出现此问题是因为您的表不是空的。 所以你应该添加新字段而不像外键一样附加它。 public int? MedicalGroupId { get; set; }.并在包管理控制台中执行update-database 命令。 然后用正确的数据填充此表(客户端)中的字段(值存在于 MedicalGroupsId 中)。 插入创建外键的行

      [ForeignKey("MedicalGroupId")]
      public virtual MedicalGroups MedicalGroup { get { return _MedicalGroup; } set { _MedicalGroup = value; } }
      

      最后执行update-database命令。会好的。

      【讨论】:

        【解决方案6】:

        我得到了我的问题的解决方案。问题是我在客户表中的“数据”。因为我的客户表具有实际不存在的医疗组 ID 值,这就是它在外键约束上给我错误的原因。

        Update Client set MedicalGroupId = NULL
        

        【讨论】:

        • 在这种情况下,请将 Cory 或我的答案标记为解决方案,因为这是我们建议检查的内容。
        【解决方案7】:

        我在设置 defaultValue 时也遇到了这个问题,给出:

        “对象依赖于列 ALTER TABLE ALTER COLUMN 失败,因为一个或多个对象访问此列”。

        最终将 AddForeignKey/DropForeignKey 移动到新的迁移并在单独的更新数据库命令中运行它们(不要在一个命令中执行两个迁移,然后它对我来说失败了。)

            public override void Up()
            {
                CreateTable(
                    "dbo.DecisionAccesses",
                    c => new
                    {
                        Id = c.Int(nullable: false),
                        Name = c.String(nullable: false, maxLength: 50),
                    })
                    .PrimaryKey(t => t.Id);
        
                CreateTable(
                    "dbo.DecisionPersonStatus",
                    c => new
                    {
                        Id = c.Int(nullable: false),
                        Name = c.String(nullable: false, maxLength: 50),
                    })
                    .PrimaryKey(t => t.Id);
        
                AddColumn("dbo.DecisionForm_DecisionFields", "DecisionAccessId", c => c.Int(nullable: false, defaultValue: (int)DecisionAccess.Creator));
                AddColumn("dbo.DecisionMatterPersons", "DecisionPersonStatusId", c => c.Int(nullable: false, defaultValue: (int)DecisionAccess.Creator));
                CreateIndex("dbo.DecisionForm_DecisionFields", "DecisionAccessId");
                CreateIndex("dbo.DecisionMatterPersons", "DecisionPersonStatusId");
                //I moved outcommented to next migration and ran the migrations in separate steps to avoid: (The object is dependent on column ALTER TABLE ALTER COLUMN failed because one or more objects access this column)
                //AddForeignKey("dbo.DecisionForm_DecisionFields", "DecisionAccessId", "dbo.DecisionAccesses", "Id", cascadeDelete: true); 
                //AddForeignKey("dbo.DecisionMatterPersons", "DecisionPersonStatusId", "dbo.DecisionPersonStatus", "Id", cascadeDelete: true);
            }
        
        
            public override void Down()
            {
                //Moved to next migration
                //DropForeignKey("dbo.DecisionMatterPersons", "DecisionPersonStatusId", "dbo.DecisionPersonStatus");
                //DropForeignKey("dbo.DecisionForm_DecisionFields", "DecisionAccessId", "dbo.DecisionAccesses");
            }
        

        【讨论】:

          【解决方案8】:

          假设您的迁移顺序正确,即与外键关联的表将在引用之前创建。请按照以下步骤操作:

          1. 从 SQL 管理工作室备份当前数据库(如果需要)
          2. 从 SQL 管理工作室中删除数据库
          3. 在 Visual Studio 的“包管理器控制台”中键入“更新数据库”

          【讨论】:

            【解决方案9】:

            如果子表中有孤立记录,也会发生此错误。清理数据库应该可以解决问题。

            【讨论】:

              【解决方案10】:

              在包管理器控制台中运行 Add-Migration InitialCreate –IgnoreChanges 命令。这会创建一个以当前模型作为快照的空迁移。

              在包管理器控制台中运行 Update-Database 命令。这会将 InitialCreate 迁移应用到数据库。由于实际的迁移不包含任何更改,它只会在 __MigrationsHistory 表中添加一行,表明该迁移已被应用。

              您可以在此处获取更多详细信息:https://msdn.microsoft.com/en-us/library/dn579398(v=vs.113).aspx

              【讨论】:

                【解决方案11】:

                我也收到了这条消息。问题是数据库中的测试数据不正确。 我在测试时没有验证,因此对于不允许空值的字段,我的 ID 为空值。修复数据后,update-database 命令运行成功。

                【讨论】:

                  【解决方案12】:

                  有这个问题,但幸运的是我只是在建表。我在每张桌子上只有几个样品。删除了两个表中的所有行,然后它就起作用了。我是菜鸟,所以值得一试

                  【讨论】:

                    【解决方案13】:

                    您还可以通过

                    使用数据播种
                    modelBuilder.Entity<MedicalGroups>()
                    .HasData(new MedicalGroups { ... }, new MedicalGroups { ... })
                    

                    在您的 DbContexts 类 OnModelCreating 方法中。

                    这样,您可以插入引用表中缺少 Id 的所有 MedicalData 行。至少在我的情况下,数据在需要时被播种并且更新数据库正常工作。

                    【讨论】:

                      猜你喜欢
                      • 2014-03-17
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2023-03-29
                      • 1970-01-01
                      • 2018-06-10
                      相关资源
                      最近更新 更多