添加外键时首先在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字段的主要内容,如果未能解决你的问题,请参考以下文章
oracle为表建立外键时没有命名FOREIGN KEY约束,现在想删外键怎么办??