对于1:2关系,请使用"每层次表继承"



我有下面的Jobcard类,它有两个子类MechanicalJobcardPanelbeatingJobcard

public abstract class Jobcard : Entity, IAggregateRoot
{
public int VehicleId { get; private set; }
public int JobcardTypeId { get; protected set; }
public string Opened_By { get; private set; } //TODO Identity Sever
public DateTime Open_Date { get; private set; }
public Vehicle Vehicle { get; private set; }
public JobcardType JobcardType { get; private set; }
public Jobcard()
{
Opened_By = "Job card opener";
Open_Date = DateTime.Now;
}
}
public class PanelBeatingJobcard : Jobcard
{
public PanelBeatingJobcard()
{
JobcardTypeId = 1;
}
}
public class MechanicalJobcard: Jobcard
{
public MechanicalJobcard()
{
JobcardTypeId = 2;
}
}

我有一辆同时有MechanicalJobcardPanelbeatingJobcard的车

public class Vehicle: Entity, IAggregateRoot
{
public int Id{ get; set; }
//Other properties here...
public PanelBeatingJobcard PanelBeatingJobcard { get; set; }
public MechanicalJobcard MechanicalJobcard { get; set; }
}

我似乎可以使用流利的API将这些映射到数据库。

我试过

class PanelBeatingJobCardEntityTypeConfiguration: IEntityTypeConfiguration<PanelBeatingJobcard>
{
public void Configure(EntityTypeBuilder<PanelBeatingJobcard> panelBeatinglJobcardConfig)
{
panelBeatinglJobcardConfig.HasOne(j => j.Vehicle).WithOne(v => v.PanelBeatingJobcard).HasForeignKey<Jobcard>(j => j.VehicleId);
}
}
class MechanicalJobcardEntityTypeConfiguration: IEntityTypeConfiguration<MechanicalJobcard>
{
public void Configure(EntityTypeBuilder<MechanicalJobcard> mechanicalJobcardConfig)
{
mechanicalJobcardConfig.HasOne(j => j.Vehicle).WithOne(v => v.MechanicalJobcard).HasForeignKey<Jobcard>(j => j.VehicleId);
}
}

但我在Add-Migration上得到以下错误:

You are configuring a relationship between 'PanelBeatingJobcard' and 'Vehicle' but have specified a foreign key on 'Jobcard'. The foreign key must be defined on a type that is part of the relationship

如果我删除这两种配置,我会在Add-Migration上得到以下错误:

Both relationships between 'Jobcard.Vehicle' and 'Vehicle' and between 'MechanicalJobcard' and 'Vehicle.MechanicalJobcard' could use {'VehicleId'} as the foreign key. To resolve this configure the foreign key properties explicitly on at least one of the relationships.

编辑:

如果按照注释中的建议将实体类型配置更改为以下内容:

class PanelBeatingJobCardEntityTypeConfiguration: IEntityTypeConfiguration<PanelBeatingJobcard>
{
public void Configure(EntityTypeBuilder<PanelBeatingJobcard> panelBeatinglJobcardConfig)
{
panelBeatinglJobcardConfig.HasOne(j => j.Vehicle).WithOne(v => v.PanelBeatingJobcard).HasForeignKey<PanelBeatingJobcard>(j => j.VehicleId);
}
}
class MechanicalJobcardEntityTypeConfiguration: IEntityTypeConfiguration<MechanicalJobcard>
{
public void Configure(EntityTypeBuilder<MechanicalJobcard> mechanicalJobcardConfig)
{
mechanicalJobcardConfig.HasOne(j => j.Vehicle).WithOne(v => v.MechanicalJobcard).HasForeignKey<MechanicalJobcard>(j => j.VehicleId);
}
}

我在迁移文件中得到了重复的VehicleId密钥(VehicleIdVehicleId1(

table.ForeignKey(
name: "FK_jobcard_vehicles_VehicleId",
column: x => x.VehicleId,
principalSchema: "dbo",
principalTable: "vehicles",
principalColumn: "VehicleId",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_jobcard_vehicles_VehicleId1",
column: x => x.VehicleId,
principalSchema: "dbo",
principalTable: "vehicles",
principalColumn: "VehicleId",
onDelete: ReferentialAction.Cascade);

我创建了一个完整的工作示例,在创建初始迁移时没有任何问题。它们映射到同一个表并使用相同的外键。

添加HasBaseType可能是个问题。这将指示EF这两个实体共享一个基本类型。

class Program
{
static void Main()
{
}
public class Vehicle
{
public int Id { get; set; }
public PanelBeatingJobcard PanelBeatingJobcard { get; set; }
public MechanicalJobcard MechanicalJobcard { get; set; }
}
public abstract class Jobcard
{
public int Id { get; set; }
public int VehicleId { get; set; }
public Vehicle Vehicle { get; set; }
}
public class PanelBeatingJobcard : Jobcard { }
public class MechanicalJobcard : Jobcard { }
public class Context: DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MechanicalJobcard>(buildAction =>
{
buildAction.HasBaseType<Jobcard>();
buildAction.HasOne(e => e.Vehicle).WithOne(e => e.MechanicalJobcard).HasForeignKey<MechanicalJobcard>(e => e.VehicleId);
});
modelBuilder.Entity<PanelBeatingJobcard>(buildAction =>
{
buildAction.HasBaseType<Jobcard>();
buildAction.HasOne(e => e.Vehicle).WithOne(e => e.PanelBeatingJobcard).HasForeignKey<PanelBeatingJobcard>(e => e.VehicleId);
});
}
}
}

迁移输出

public partial class InitialMigration : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Vehicle",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1")
},
constraints: table =>
{
table.PrimaryKey("PK_Vehicle", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Jobcard",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
VehicleId = table.Column<int>(type: "int", nullable: false),
Discriminator = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Jobcard", x => x.Id);
table.ForeignKey(
name: "FK_Jobcard_Vehicle_VehicleId",
column: x => x.VehicleId,
principalTable: "Vehicle",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Jobcard_VehicleId",
table: "Jobcard",
column: "VehicleId",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Jobcard");
migrationBuilder.DropTable(
name: "Vehicle");
}
}

最新更新