Tabellen keine Primärschlüssel teilen Werte
So gibt es keine Möglichkeit, dies zu einer Vererbungsschema abzubilden, die TPT hätte sein sollen. Die unterschiedlichen Primärschlüsselwerte verhindern dies.
Was übrig bleibt, ist die Zuordnung verschiedener Klassen, die miteinander verbunden sind, so dass Sie zumindest Navigationseigenschaften verwenden können, anstatt manuell nicht verbundene Entitäten zu verknüpfen. Ich habe einen Weg gefunden, dies zu tun, aber es ist nicht ideal. Eigentlich ist es ziemlich künstlich. Aber sehen Sie, ob es eine brauchbare Lösung für Sie ist.
benutzte ich diese Klassen:
public abstract class Vehicle
{
public int VehicleId { get; set; }
public string Name { get; set; }
public VehicleInfo VehicleInfo { get; set; }
}
public class CarVehicle : Vehicle
{ }
public class BikeVehicle : Vehicle
{ }
public abstract class VehicleInfo
{
public int ID { get; set; }
}
public class CarInfo : VehicleInfo
{
public string Model { get; set; }
}
public class BikeInfo : VehicleInfo
{
public bool IsEbike { get; set; }
}
I Tisch CarVehicle
und BikeVehicle
von TPHVehicle
in den Einheiten aufgeteilt:
modelBuilder.Entity<Vehicle>().ToTable("Vehicle");
modelBuilder.Entity<Vehicle>()
.Map<CarVehicle>(m => m.Requires("VehicleType").HasValue("Car"))
.Map<BikeVehicle>(m => m.Requires("VehicleType").HasValue("Bike")
.HasColumnType("CHAR")
.HasMaxLength(4));
CarInfo
und BikeInfo
, auf der anderen Seite, müssen ihre eigenen haben Tabellen, also hier habe ich TPC:
verwendet
Und schließlich die Klassen verbindet:
modelBuilder.Entity<Vehicle>().HasRequired(c => c.VehicleInfo)
.WithOptional().Map(m => m.MapKey("SubId"));
Durch den Basistyp VehicleInfo
Verwendung es möglich ist, eine Eigenschaft Vehicle.VehicleInfo
durch einen Fremdschlüssel SubId
abzubilden. Es ist nicht möglich, dies zu haben:
public class CarVehicle : Vehicle
{
public CarInfo CarInfo { get; set; }
}
public class BikeVehicle : Vehicle
{
public BikeInfo BikeInfo { get; set; }
}
EF wird es nicht akzeptieren, wenn Sie versuchen, beide Navigationseigenschaften durch SubId
abzubilden.
Der Hauptnachteil dieses Modells ist, dass Sie immer die "Info" Entitäten als VehicleInfo
Objekte erhalten müssen.EF erstellt die richtigen Subtypen, aber ihr Kompilierungszeittyp ist VehicleInfo
. Wenn Sie die VehicleInfo
-Eigenschaft festlegen, müssen Sie ebenfalls daran denken, den richtigen Typ anzugeben. Sie können etwas, dass das Eigentum von einer Passthrough mildern ...
public class CarVehicle : Vehicle
{
[NotMapped]
public CarInfo CarInfo
{
get { return VehicleInfo as CarInfo; }
set { VehicleInfo = value; }
}
}
... und das gleiche in BikeVehicle
. Sie können diese Eigenschaft jedoch nicht direkt in einer LINQ-Abfrage verwenden, da sie nicht zugeordnet ist (und nicht zugeordnet werden kann).
Ferner kann die ausgeführten SQL von etwas Einfachen wie ...
db.Set<CarVehicle>().Include(c => c.VehicleInfo).ToList();
... ist humongous wegen EF durch alle Vererbungs Bäume zu graben.
Wenn Sie das DB-Schema nicht ändern können, erstellen Sie nur 3 unabhängige Klassen ohne Vererbungsstrategie und Navigationseigenschaften wie 'Car.Vehicle', da sie nur im Fall von FKs möglich sind. –
Dank @SlavaUtesinov, es scheint, dass Sie Recht haben. – Tony