【问题标题】:Entity Framework Core - Foreign Key 1 (extra foreign key column)Entity Framework Core - 外键 1(额外的外键列)
【发布时间】:2017-09-26 23:23:27
【问题描述】:

我刚刚升级到 Entity Framework Core 2,现在我遇到了一个额外的列存在的问题,它有一个唯一的键,即使它不在我的模型中,也没有在其他任何地方定义。

索引:

migrationBuilder.CreateTable(
    name: "Vouchers",
    columns: table => new
    {
        Id = table.Column<int>(nullable: false)
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
        Code = table.Column<Guid>(nullable: false),
        IsClaimed = table.Column<bool>(nullable: false),
        LastModified = table.Column<DateTime>(nullable: false),
        NumberOfUnits = table.Column<int>(nullable: false),
        TransactionId = table.Column<int>(nullable: false),
        TransactionId1 = table.Column<int>(nullable: true) // why is this here?
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Vouchers", x => x.Id);
        table.ForeignKey(
            name: "FK_Vouchers_Transactions_TransactionId1",
            column: x => x.TransactionId1,
            principalTable: "Transactions",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    });

TransactionId1 不在模型中:

public class Voucher : IAutoLastModified
{
    public int Id { get; set; }
    public DateTime LastModified { get; set; }

    public int TransactionId { get; set; }
    public Transaction Transaction { get; set; }

    public int NumberOfUnits { get; set; }
    public Guid Code { get; set; }
    public bool IsClaimed { get; set; }
}

我是否错误地定义了外键?

modelBuilder.Entity<Voucher>().HasOne(x => x.Transaction).WithOne(x => x.Voucher).IsRequired(false);

我的应用程序失败,因为 TransactionId1 总是为空,并且有一个我无法删除的唯一约束。

EF 为什么要为这个表创建一个额外的列?

【问题讨论】:

    标签: c# entity-framework ef-model-first


    【解决方案1】:

    如果您以两种方式定义模型但忘记在 fluent 中使用它,也可能会发生这种情况:

    public class Customer
    {
        public Guid Id { get; set; }
        public List<Order> Orders {get; set;}
    }
    
    public class Order
    {
        public Guid Id { get; set; }
        
        public Guid CustomerId { get; set; }
        public Guid Customer { get; set; }
    }
    
    // AppDbContext
    builder.Entity<Order>()
         .HasOne(x => x.Customer) // <-- EDIT: Also use it like this, not .HasOne<Customer>()
         .WithMany() //WRONG -> should be .WithMany(x => x.Orders) OR modify the model to not define the collection at the customer entity
         .HasForeignKey(x => x.CustomerId)
         .OnDelete(DeleteBehavior.SetNull)
    ;
    

    【讨论】:

    • 谢谢!我花了将近一天的时间,而且会花更多的时间,这对我很有帮助。
    【解决方案2】:

    好的,所以我弄清楚了问题所在(将问题留在这里,供任何犯过我同样错误的人参考)。

    我将关系标记为可选,但该列是 int 而不是 int?,因此 EF 决定在幕后添加它自己的列。

    修复此问题后,我不得不重新创建数据库 - 由于现有数据,迁移未成功完成。

    【讨论】:

      【解决方案3】:

      当子项中的外键字段类型与父项中的主键字段类型不匹配时,我遇到了这个问题。

      示例:

      public class User // Parent
      {
          public long Id { get; set; }
          public virtual ICollection<UserLike> UserLikes { get; set; } // Child collection
      }
      
      public class UserLike // Child
      {
          public int Id { get; set; }
          public int UserId { get; set; } // Foreign key
          public virtual User User { get; set; } // Navigation property
      }
      

      DbContext 中,我有:

      modelBuilder.Entity<UserLike>(entity =>
      {
          entity.HasOne(x => x.User)
          .WithMany(x => x.UserLikes)
          .OnDelete(DeleteBehavior.ClientCascade);
      }
      

      这里,int UserId 与父级中的主键 long Id 的类型不匹配。解决方法是使UserIdlong:

      public class UserLike // Child
      {
          public int Id { get; set; }
          public long UserId { get; set; } // Foreign key
          public virtual User User { get; set; } // Navigation property
      }
      

      【讨论】:

        【解决方案4】:

        您需要告诉模型构建器您要将voucher 表中的哪一列用作外键列。否则 Entity Framework 只会为你创建一个。

        为此,请将HasForeignKey 方法添加到流利设置中:

        modelBuilder.Entity<Voucher>().HasOne(x => x.Transaction).WithOne(x => x.Voucher).HasForeignKey<Voucher>(x => x.TransactionId).IsRequired(false);
        

        请注意,在建立一对一关系时,您需要将外键所在的实体定义为通用约束。

        【讨论】:

          【解决方案5】:

          我过去曾使用数据优先方法遇到过这个问题。我不得不删除一个现有的列,但在每次更新后,该列出现在 edmx 模式结构中,我必须手动删除它才能使其工作。你能重新创建 edmx 而不是更新吗?

          【讨论】:

            【解决方案6】:

            我遇到了同样的问题,我的解决方法是在导航属性上方添加 [ForeignKey("")] 的 DataAnnotation 标记,以明确说明要使用哪一个。

            public Guid TransactionId { get; set; }
            
            [ForeignKey("TransactionId ")]
            public Transaction Transaction { get; set; }
            

            谢谢

            【讨论】:

              猜你喜欢
              • 2022-09-22
              • 1970-01-01
              • 2017-08-17
              • 2016-12-16
              • 2018-09-28
              • 1970-01-01
              • 2018-08-19
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多