EF Core在许多表上的一对一关系允许重复的条目

时间:2019-02-16 14:40:26

标签: sql-server entity-framework entity-framework-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();

可以正常工作并创建以下数据 enter image description here

当我去PetrolCar时,我插入了CarId = 1的新行,尽管CarId在ElectricCar表中用作CarId,但它接受了该行而没有给出任何错误。 有什么方法可以限制这一点吗?

1 个答案:

答案 0 :(得分:0)

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

代码解决方案中的一种可能(尽管它不是特别干净,所以我建议以此为基础来重组数据,尽管这似乎是您希望避免的事情)是重写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中具有相同ID的汽车的其他情况)。其他方向)