ef core 迁移时(add-migration) 报 外键 约束 错
建了两个 一对一的实体
/// <summary> /// 分布分项 这个因为abp 原因 ,sql 的表名很长 大概是 ConstructionBase_Subitem /// </summary> public class SubItem : FullAuditedEntity<Guid> { public SubItemContent SubItemContent { get; set; } public string Name { get; set; } public IdentityUser Creator { get; set; } public Guid? ProjectId { get; set; } public Project.Project Project { get; set; } }
/// <summary> /// 分布分项 - 详情 这个表名也很长 是 ConstructionBase_SubitemContent /// </summary> public class SubItemContent : FullAuditedEntity<Guid>, IGuidKeyTree<SubItemContent> { /// <summary> /// 分布分项 实体 id /// </summary> public Guid? SubItemId { get; set; } /// <summary> /// 关联 分布分项 实体 /// </summary> public SubItem SubItem { get; set; } /// <summary> /// 节点名称 /// </summary> public string Name { get; set; } /// <summary> /// 节点类型 /// </summary> public NodeType NodeType { get; set; } /// <summary> /// 排序 (用于上移、下移) /// </summary> public int Order { get; set; } public Guid? ParentId { get; set; } public SubItemContent Parent { get; set; } public List<SubItemContent> Children { get; set; } }
然后 执行 迁移 ,默认 ef core 会给 这两个 实体 指定 外键关系 (不写 那个 b.HasOne(p => p.SubItem).WithOne(b => b.SubItemContent).HasForeignKey<SubItemContent>(p => p.SubItemId)也行,因为在实体里面已经定义好了)
但是这个时候 迁移会报错
错误如下 :
The foreign keys {'SubItemId'} on 'SubItemContent' and {'ParentId'} on 'SubItemContent' are both mapped to 'Sn_ConstructionBase_SubItemContent.FK_Sn_ConstructionBase_SubItemContent_Sn_ConstructionBase_SubI~' but referencing different principal tables ('Sn_ConstructionBase_SubItem' and 'Sn_ConstructionBase_SubItemContent').
翻译过来是
'SubItemContent' 上的外键 {'SubItemId'} 和 'SubItemContent' 上的 {'ParentId'} 都映射到 'Sn_ConstructionBase_SubItemContent.FK_Sn_ConstructionBase_SubItemContent_Sn_ConstructionBase_SubI~',但引用了不同的主体表('Sn_ConstructionBase_SubItem' 和'_Sn_SubItemContent')。

就是Content两个外键(SubItem和 Parent) 但是却映射到了 一个 外键约束名上面 了 ,因为 数据库 (pg 和 mysql) 对 外键约束名 的长度 有限制 ,又因为 数据表的前缀 太长了 ,两个 外键约束名最后 的长度都 被截断了,变成
'Sn_ConstructionBase_SubItemContent.FK_Sn_ConstructionBase_SubItemContent_Sn_ConstructionBase_SubI~'
这个相同的外键约束名了 ,从而 报错……
解决方法 就是 得写 这个 builder 的配置
b.HasOne(p => p.SubItem) .WithOne(b => b.SubItemContent) .HasForeignKey<SubItemContent>(p => p.SubItemId) // 一对一要这样写 HasForeignKey<T>(p=>p.xxId) 不写泛型代码提示报错,百度下ef core 一对一 .HasConstraintName("ForeignKey_SubItem_SubItemContent"); // 这里是 给 外键约束 取名 因为外键约束名太长,多个外键 名 重复了 ,ef core 迁移会报错……
其中 的 .HasConstraintName("ForeignKey_SubItem_SubItemContent"); 就是指定 外键约束名,把他的 名字 取的短一些 就 不会报错了 ,不写的话 ef core就 给你分配,分配的 会加上 前缀 导致太长了
然后迁移 + 更新数据库

可以看到 自己定义 的外键约束名已经 变了 ,这样两个 就不冲突 了

浙公网安备 33010602011771号