首页 > 解决方案 > 许多表上的 EF Core 一对一关系允许重复条目

问题描述

我正在使用 EF Core,并尝试在三个表(Car、ElectricCar 和 PetrolCar)之间创建一对一的关系

public class Car
{
    public int Id { get; set; }
    public string RegistrationNumber { get; set; }

    public ElectricCar Company { get; set; }
    public PetrolCar Trust { get; set; }
}

public class ElectricCar
{
    public int ElectricCarId { get; set; }
    public double BatteryCapacityWattage{ get; set; }

    public int CarId { get; set; }
    public Car Car { get; set; }
}

public class PetrolCar
{
    public int PetrolCarId { get; set; }
    public double TankCapacity { get; set; }

    public int CarId { get; set; }
    public Car Car { get; set; }
}


public partial class CarDbContext : Microsoft.EntityFrameworkCore.DbContext
{
    public CarDbContext()
    {
    }

    public CarDbContext(DbContextOptions<CarDbContext> options)
        : base(options)
    {
    }

    public DbSet<ElectricCar> ElectricCar { get; set; }
    public DbSet<Car> Car { get; set; }
    public DbSet<PetrolCar> PetrolCar { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer("Server=DESKTOP-PC\\SQLLOCAL;Database=OneToOneEFCoreCar;Trusted_Connection=True;");
        }
    }
}

以及插入数据的代码:

CarDbContext context = new CarDbContext();

context.Car.Add(new Car
{
    RegistrationNumber = "EL123",
    Company = new ElectricCar() { BatteryCapacityWattage = 2000 }
});

context.Car.Add(new Car
{
    RegistrationNumber = "PETR123",
    Trust = new PetrolCar() {  TankCapacity = 50 }
});
context.SaveChanges();

这没有任何问题,并创建以下数据 在此处输入图像描述

当我去 PetrolCar 时,我插入了一个 CarId = 1 的新行,它接受它而不给出任何错误,尽管 CarId 在 ElectricCar 表中用作 CarId。有没有办法限制这个?

标签: sql-serverentity-frameworkentity-framework-core

解决方案


如果您完全致力于保持您的对象模型/数据结构与上面的相同,那么两个表之间的唯一约束实际上是无法实现的。

代码解决方案中的一种可能(尽管它不是特别干净,所以我建议在此之上重构您的数据,尽管这似乎是您想要避免的事情)是覆盖该SaveChanges方法。

类似于:

public override SaveChanges()
{
    var petrolCars = ChangeTracker.Entries().Where(e is PetrolCar).ToList();

    foreach(var pCar in petrolCars)
    { 
        if(query the database for electric cars to see if car id exists)
        {
            do some sort of error processing and avoid saving;
        }
    }

    base.SaveChanges();
}

它确实意味着创建一个从默认上下文继承的上下文类,尽管它在执行此类操作方面增加了很多灵活性(显然,您也希望处理其他情况,即在另一个方向上具有相同 id 的汽车)


推荐阅读