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就 给你分配,分配的 会加上 前缀 导致太长了 

然后迁移 + 更新数据库

 

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

 

posted @ 2021-06-02 09:11  ifnk  阅读(551)  评论(0)    收藏  举报