Entity Framework one-to-many with table-per-hierarchy creates one foreign key column per subclass

c#, entity-framework, one-to-many, table-per-hierarchy

Solution

Use attribute [Column("GarageId")] on GarageId property on both car and motorcycle class.

Problem

I have a `Garage` which contains `Cars` and `Motorcycles`. Cars and motorcycles are `Vehicles`. Here they are: ``` public class Garage { public int Id { get; set; } public virtual List<Car> Cars { get; set; } public virtual List<Motorcycle> Motorcycles { get; set; } public Garage() { Cars = new List<Car>(); Motorcycles = new List<Motorcycle>(); } } public abstract class Vehicle { public int Id { get; set; } public string Make { get; set; } public string Model { get; set; } } public class Car : Vehicle { public int GarageId { get; set; } public virtual Garage Garage { get; set; } // some more properties here... } public class Motorcycle : Vehicle { public int GarageId { get; set; } public virtual Garage Garage { get; set; } // some more properties here... } ``` Why do Car and Motorcycle each have a GarageId and Garage property? If I push those properties up to the Vehicle superclass, EF complains and tells me navigation properties must reside in concrete classes. Moving on, here's my DbContext: ``` public class DataContext : DbContext { public DbSet<Garage> Garages { get; set; } public DbSet<Vehicle> Vehicles { get; set; } public DbSet<Car> Cars { get; set; } public DbSet<Motorcycle> Motorcycles { get; set; } public DataContext() : base("GarageExample") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); } } ``` And here's a short program to play with my toys: ``` class Program { static void Main(string[] args) { Database.SetInitializer<DataContext>(new DropCreateDatabaseAlways<DataContext>()); using (var db = new DataContext()) { var car1 = new Car { Make = "Subaru", Model = "Legacy" }; var car2 = new Car { Make = "Porche", Model = "911" }; var bike1 = new Motorcycle { Make = "Suzuki", Model = "GS500" }; var bike2 = new Motorcycle { Make = "Kawasaki", Model = "Ninja" }; var garage = new Garage(); garage.Cars.Add(car1); garage.Cars.Add(car2); garage.Motorcycles.Add(bike1); garage.Motorcycles.Add(bike2); db.Garages.Add(garage); db.SaveChanges(); } } } ``` The program runs, and produces the following Vehicles table: ``` Id Make Model GarageId GarageId1 Discriminator 1 Subaru Legacy 1 null Car 2 Porche 911 1 null Car 3 Suzuki GS500 null 1 Motorcycle 4 Kawasaki Ninja null 1 Motorcycle ``` With both Car and Motorcycle having their own GarageId and Garage properties, it seems that each subclass is creating its own foreign key to garage. How do I tell EF (via the fluent api, if possible) that Car.Garage and the Motorcycle.Garage are the same thing, and should use the same column? This is the Vehicles table I want, of course: ``` Id Make Model GarageId Discriminator 1 Subaru Legacy 1 Car 2 Porche 911 1 Car 3 Suzuki GS500 1 Motorcycle 4 Kawasaki Ninja 1 Motorcycle ```

Original source

Related problems