Utilizzo EF Core e ho cercato di creare una relazione uno a uno tra tre tavoli (Car, ElectricCar e 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;");
}
}
}
e il codice che inserisce i dati:
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();
Funziona senza problemi e crea i seguenti dati
Quando vado al PetrolCar inserisco una nuova riga con CarId = 1 e la accetta senza dare alcun errore sebbene CarId sia usato nella tabella ElectricCar come CarId. C'è un modo per limitare questo?
Se sei completamente impostato per mantenere i tuoi modelli di oggetti / struttura dei dati come è sopra, allora un vincolo unico tra le due tabelle non è nativamente realizzabile.
Una soluzione in codice possibile (sebbene non sia particolarmente pulita, quindi suggerirei di ristrutturare i dati su questo, anche se questo sembra essere qualcosa che vorreste evitare) è di sovrascrivere il metodo SaveChanges
.
qualcosa sulla falsariga di:
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();
}
Significa creare una classe di contesto che eredita dal contesto predefinito, sebbene aggiunga molta flessibilità in termini di fare qualcosa di simile (ovviamente si vorrebbe gestire anche gli altri casi di macchine che hanno lo stesso id nella direzione opposta)