【问题标题】:Foreign Key already exists For Relation Error in EF6EF6 中的关系错误外键已存在
【发布时间】:2021-04-14 19:36:01
【问题描述】:

我正在使用带有 Npgsql 和代码优先方法的 Entity Framework 6.4.x。

我创建了以下实体:

    public class UserBankAccountTransaction
    {
        public long PayerBankAccountId { get; set; }
        
        [ForeignKey(nameof(PayerBankAccountId))]
        public virtual UserBankAccount PayerBankAccount { get; set; }
        
        public long PayeeBankAccountId { get; set; }
        
        [ForeignKey(nameof(PayeeBankAccountId))]
        public virtual UserBankAccount PayeeBankAccount { get; set; }
        
        [Required]
        public int Amount { get; set; }
    }

就是这样,现在当我执行Add-Migration 时,它会创建以下迁移:

    CreateTable(
                "public.UserBankAccountTransactions",
                c => new
                    {
                        Id = c.Long(nullable: false, identity: true),
                        PayerBankAccountId = c.Long(nullable: false),
                        PayeeBankAccountId = c.Long(nullable: false),
                        Amount = c.Int(nullable: false),
                        CreatedDate = c.DateTime(nullable: false),
                        ModifiedDate = c.DateTime(nullable: false),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("public.UserBankAccounts", t => t.PayeeBankAccountId, cascadeDelete: true)
                .ForeignKey("public.UserBankAccounts", t => t.PayerBankAccountId, cascadeDelete: true)
                .Index(t => t.PayerBankAccountId)
                .Index(t => t.PayeeBankAccountId);

正如您在上面自动生成的迁移中看到的那样,"public.UserBankAccounts" 是一个外键,被生成了两次同名。

因此当我Update-Migration 时出现此错误:

constraint "FK_public.UserBankAccountTransactions_public.UserBankAccounts_P" for relation "UserBankAccountTransactions" already existsa

问题

没有办法在 EF6 的同一张表中添加多个引用/外键吗?

【问题讨论】:

    标签: c# entity-framework-6 npgsql


    【解决方案1】:

    Postgres 对标识符的最大长度有限制 - 63 bytes,因此您的两个外键最终都具有相同的名称 - FK_public.UserBankAccountTransactions_public.UserBankAccounts_P

    所以你需要找到一种方法来指定 FK 名称。不确定它是否可以通过属性/流利的 api 完成(至少我无法找到它)但作为解决方法,您应该能够通过生成的迁移中的TableBuilder<TColumns>.ForeignKey 方法的name 参数指定它(即通常不是一件好事):

    .ForeignKey("public.UserBankAccounts", t => t.PayeeBankAccountId, cascadeDelete: true, name: "FK_UBAT_UBA_PayeeBankAccountId" )
    .ForeignKey("public.UserBankAccounts", t => t.PayerBankAccountId, cascadeDelete: true, name: "FK_UBAT_UBA_PayerBankAccountId")
    

    【讨论】:

    • 那是UP的,我可以在那里修改,但是Down呢?并不是说我关心 Down,因为我通常永远不会“Down”,我通常只会在迁移中“UP”,只是一般性地询问。
    • @user1735921 在这种情况下,“Down”应该删除带有所有 FK 的表,因此无需更改任何内容。
    【解决方案2】:

    我也有同样的问题,但Sql server 是这样解决的:

    public class UserBankAccountTransaction
        {
            [ForeignKey(nameof(PayerBankAccount))]
            public long PayerBankAccountId { get; set; }
            
            public virtual UserBankAccount PayerBankAccount { get; set; }
            
            [ForeignKey(nameof(PayeeBankAccount))]
            public long PayeeBankAccountId { get; set; }
            
            public virtual UserBankAccount PayeeBankAccount { get; set; }
            
            [Required]
            public int Amount { get; set; }
        }
    
    public class UserBankAccount 
    {
        //other properties
    
        [InverseProperty(nameof(UserBankAccountTransaction.PayerBankAccount))]
        public UserBankAccountTransaction PayerUserBankAccountTransaction { get; set; } 
    
        //or public List<UserBankAccountTransaction> PayerUserBankAccountTransactions { get; set; }
    
        [InverseProperty(nameof(UserBankAccountTransaction.PayeeBankAccount))]
        public UserBankAccountTransaction PayeeUserBankAccountTransaction { get; set; } // or list ...
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-13
      • 1970-01-01
      • 2022-06-26
      相关资源
      最近更新 更多