在实体框架中更新数据库,代码优先迁移,我收到此错误:
ALTER TABLE语句与FOREIGN KEY约束“FK_dbo.Clients_dbo.MedicalGroups_MedicalGroupId”冲突 . 冲突发生在数据库“hrbc”,表“dbo.MedicalGroups”,列“Id”中 .
这是我的 class :
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");
}
9 回答
检查数据库中是否存在与FK约束冲突的现有数据,从而导致创建失败 .
我认为@Cory让你接近正确的解决方案,你只是没有花时间去调查 .
在添加迁移代码中,可能会生成迁移
注意可以为空:false;如果你的模型的Id为int而不是int? (nullable int)迁移代码将nullable设置为false . 您的模型显示您使用的是不可为空的int,默认为0,并且您可能没有值为0的外键项 .
现在,您必须创建一个默认值,该值存在于外键表中,或者创建约束而不检查您是否使用SQL Server来创建约束 . 但请记住:如果使用[DefaultValue(0)]属性装饰属性,则如果指定了默认值,则不会更改现有数据,如SQL Column Add .
我建议您更改模型类以允许可为空的int . 然后,在种子方法中,针对dbcontext创建一个简单方法,以使用默认值更新新列,因为数据注释中的[DefaultValue]属性不会修改您的数据 .
添加 - 迁移/更新 - 数据库以创建列和约束 . 接下来,如果您希望允许非可空int,并假设您已将所有行更改为外键的某个有效值,请再次修改模型,Add-Migration / Update-database . 这为您的模型迁移提供了一个完整的链 . 稍后当您发布到实际站点时会派上用场,因为您的数据模型更改流程将保持不变 .
此错误告诉您正在违反外键约束 . 要解决你有一些解决方案
Fix your data - 某处
Clients
表中有一些记录,其中有一个在MedicalGroups
表中不存在的MedicalGroupId . 编写查询以查找MedicalGroups
表中不存在的ID,并自行手动修复数据 .Remove the foreign key constraint - 显然,如果删除外键约束,您将不再受此消息的干扰 . 不幸的是,数据库将不再强制执行这种关系,并可能在将来使这个问题变得更糟 .
Create constraint using WITH NOCHECK - 您可以使用
WITH NOCHECK
选项创建外键约束 . 此选项告诉SQL Server不将此约束应用于现有数据 . SQL Server将在任何将来的INSERTS / UPDATES / DELETES中检查此约束 .出现此问题是因为您的表不为空 . 所以你要添加新字段而不像外键那样附加它 . public int? MedicalGroupId { get; set; } . 并在包管理控制台中执行update-database命令 . 然后使用正确的数据填充此表(客户端)中的字段(值存在于MedicalGroupsId中) . 插入该行以创建外键 [ForeignKey("MedicalGroupId")] public virtual MedicalGroups MedicalGroup { get { return _MedicalGroup; } set } . 最后执行update-database命令 . 一切都会安好的 .
我得到了问题的解决方案 . 问题是我在客户表中的“数据” . 因为我的客户端表具有实际上不存在的medicalgroupid值,这就是为什么它给我外键约束的错误 .
我有这个问题以及defaultValue设置,给出:
“该对象依赖于列ALTER TABLE ALTER COLUMN失败,因为一个或多个对象访问此列” .
结束将AddForeignKey / DropForeignKey移动到新的迁移并在单独的update-database命令中运行它们(不要在一个命令中执行这两个迁移,然后它就失败了 . )
对于可能在此处着陆的其他人,如果您使用的是Code-First Entity Framework并且只是尝试向具有现有数据的表添加新的必需列,则可能会有一个非常简单的修复 .
注意:在执行此操作之前,只需知道您需要为所有现有行的新列添加有效值 . 想想你将添加什么 Value 继续之前的现有行 . 您可能希望为所需的查找表提供指示“无效”或“未知”的值 .
在您的模型中,通过添加?将列设置为可为空?在int之后 . 保存并编译模型 . 运行Update-Database .
例:
在db中,通过将NULL值替换为有效的查找值来更新表 . 在我的情况下,我在 Headers 查找表中添加了“未知”,然后批量编辑所有行以引用该查找ID .
回到您的模型中,删除'?'所以该列不再可以为空 . 保存并编译模型,然后运行Update-Database
你现在应该好好去 .
假设您的迁移顺序正确,即在引用之前将创建与外键关联的表 . 请遵循以下步骤:
从SQL管理工作室备份当前数据库(如果需要)
从SQL管理工作室删除数据库
在Visual Studio中键入'Update-Database' 'Package Manager Console'
在程序包管理器控制台中运行 Add-Migration InitialCreate –IgnoreChanges 命令 . 这将创建一个空迁移,将当前模型作为快照 .
在程序包管理器控制台中运行 Update-Database 命令 . 这将将InitialCreate迁移应用于数据库 . 由于实际迁移不包含任何更改,因此只需向__MigrationsHistory表添加一行,指示已应用此迁移 .
您可以在此处获取更多详细信息:https://msdn.microsoft.com/en-us/library/dn579398(v=vs.113).aspx