添加外键时首先在EF核心代码中生成双id字段

Posted

技术标签:

【中文标题】添加外键时首先在EF核心代码中生成双id字段【英文标题】:Double id field being generated in EF core code first when adding foreign key 【发布时间】:2021-05-09 16:35:45 【问题描述】:

我正在开发一个跟踪客户汽车的应用程序。我首先使用 EF 核心代码。这就是我对车辆和牌照这两个表有问题的地方。

一辆车可以有多个车牌(但一次只能激活一个),一个车牌可以属于一辆车。到目前为止一切正常,但是对于一个新功能,我想实现汽车车牌的历史。为此,我在车辆类中添加了一个 activeLicensePlate 字段,该字段应包含 licensePlate(id 字段)表的外键。

我的代码:

Class Vehicle(添加新代码之前):

namespace Models

    public class Vehicle : IIdentifiable
    
        public virtual long Id  get; set; 
        public virtual long ChassisNr  get; set; 
        public virtual ICollection<LicensePlate> LicensePlates  get; set; 
        public virtual FuelTypes FuelType  get; set; 
        public virtual VehicleTypes VehicleType  get; set; 
        public virtual int Mileage  get; set; 
        public virtual ICollection<Maintenance> Maintenances  get; set; 
        public virtual ICollection<Application> Applications  get; set; 
        
    

类车辆(尝试添加字段以跟踪活动车牌后):

namespace Models

    public class Vehicle : IIdentifiable
    
        public virtual long Id  get; set; 
        public virtual long ChassisNr  get; set; 
        public virtual ICollection<LicensePlate> LicensePlates  get; set; 
        public virtual FuelTypes FuelType  get; set; 
        public virtual VehicleTypes VehicleType  get; set; 
        public virtual int Mileage  get; set; 
        public virtual ICollection<Maintenance> Maintenances  get; set; 
        public virtual ICollection<Application> Applications  get; set; 
        
        //not working, migration creates 2 columns
        public virtual LicensePlate ActiveLicensePlate  get; set; 
        public virtual long ActiveLicensePlateId  get; set; 
    

类车牌:

namespace Models

    public class LicensePlate : IIdentifiable
    
        public virtual long Id  get; set; 
        public virtual string LicensePlateCharacters  get; set; 

        //rel vehicle
        public virtual long VehicleId  get; set; 
        public virtual Vehicle Vehicle  get; set; 
    

模型约束:

 //rel vehicle license plate one many
modelBuilder.Entity<LicensePlate>()
.HasOne<Vehicle>(l => l.Vehicle)
.WithMany(v => v.LicensePlates)
.HasForeignKey(l => l.VehicleId)
.IsRequired();

车辆模型约束:

using Microsoft.EntityFrameworkCore;
using Models;

namespace ReadRepositories.Mappings

    public static class VehicleModelConstraints
    
        public static void OnModelCreatingVehicle(this ModelBuilder modelBuilder)
        
            modelBuilder.Entity<Vehicle>()
                .HasKey(v => v.Id);

            modelBuilder.Entity<Vehicle>()
                .Property(v => v.Id)
                .ValueGeneratedOnAdd();

            modelBuilder.Entity<Vehicle>()
                .Property(v => v.FuelType)
                .IsRequired();

            modelBuilder.Entity<Vehicle>()
                .Property(v => v.VehicleType)
                .IsRequired();

            modelBuilder.Entity<Vehicle>()
                .Property(v => v.Mileage)
                .IsRequired();

            modelBuilder.Entity<Vehicle>()
               .Property(v => v.ChassisNr)
               .IsRequired();

            modelBuilder.Entity<Vehicle>()
                .Property(v => v.ActiveLicensePlateId)
                .IsRequired();
        
    

车牌型号限制:

using Microsoft.EntityFrameworkCore;
using Models;

namespace ReadRepositories.Mappings

    public static class LicensePlateModelConstraints
    
        public static void OnModelCreatingLicensePlate(this ModelBuilder modelBuilder)
        
            modelBuilder.Entity<LicensePlate>()
               .HasKey(l => l.Id);

            modelBuilder.Entity<LicensePlate>()
                .Property(l => l.Id)
                .ValueGeneratedOnAdd();

            modelBuilder.Entity<LicensePlate>()
                .Property(l => l.LicensePlateCharacters)
                .IsRequired();
        
    


已生成迁移:

using Microsoft.EntityFrameworkCore.Migrations;

namespace Repositories.Migrations

    public partial class ActiveLicensePlate : Migration
    
        protected override void Up(MigrationBuilder migrationBuilder)
        
            migrationBuilder.AddColumn<long>(
                name: "ActiveLicensePlateId",
                table: "Vehicle",
                type: "bigint",
                nullable: false,
                defaultValue: 0L);

            migrationBuilder.AddColumn<long>(
                name: "ActiveLicensePlateId1",
                table: "Vehicle",
                type: "bigint",
                nullable: true);

            migrationBuilder.CreateIndex(
                name: "IX_Vehicle_ActiveLicensePlateId1",
                table: "Vehicle",
                column: "ActiveLicensePlateId1");

            migrationBuilder.AddForeignKey(
                name: "FK_Vehicle_LicensePlate_ActiveLicensePlateId1",
                table: "Vehicle",
                column: "ActiveLicensePlateId1",
                principalTable: "LicensePlate",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);
        

        protected override void Down(MigrationBuilder migrationBuilder)
        
            migrationBuilder.DropForeignKey(
                name: "FK_Vehicle_LicensePlate_ActiveLicensePlateId1",
                table: "Vehicle");

            migrationBuilder.DropIndex(
                name: "IX_Vehicle_ActiveLicensePlateId1",
                table: "Vehicle");

            migrationBuilder.DropColumn(
                name: "ActiveLicensePlateId",
                table: "Vehicle");

            migrationBuilder.DropColumn(
                name: "ActiveLicensePlateId1",
                table: "Vehicle");
        
    


正如您在生成的迁移中看到的那样,创建了一个名为 ActiveLicensePlateId 的字段,但也创建了一个名为 ActiveLicensePlateId1 的字段(其中包含我要添加的外键)。

迁移前我的数据库表:

车辆表:

车牌表:

所以,简单地说,我想要的“唯一”是在车辆表中添加一个字段,一个名为 activeLicensePlate 的字段。此字段应引用车牌的 ID,并带有车牌表的外键。

有人知道出了什么问题吗?

【问题讨论】:

【参考方案1】:

我不确定,但我认为您的显式属性定义使 ef 核心忽略您的外键,因为您没有标记它,所以也许只是删除它应该可以工作,因为您已经遵循命名约定

           //remove this 
            modelBuilder.Entity<Vehicle>()
                .Property(v => v.ActiveLicensePlateId)
                .IsRequired();

或者更好的方法是使用 fluent api 来定义关系

    modelBuilder.Entity<Vehicle>()
        .HasOne(p => p.ActiveLicensePlate)
        .WithOne()
        .HasForeignKey(p => p.ActiveLicensePlateId);

【讨论】:

以上是关于添加外键时首先在EF核心代码中生成双id字段的主要内容,如果未能解决你的问题,请参考以下文章

创建外键时,phpmyadmin 中的外键约束失败

添加外键时Laravel迁移错误

navicat 8.0 for mysql怎么设置外键

oracle为表建立外键时没有命名FOREIGN KEY约束,现在想删外键怎么办??

创建外键时出错:MySQL 错误 1215:无法添加外键约束 [重复]

当外键也是主键时,在 MySQL 上出现外键错误? [复制]