Search code examples
entity-frameworkinheritancetph

Conditional Mapping in Entity Framework - OR operation with TPH


We have an entity like Vehicle and three derived entities such as Car, Motorbike and Bicycle. This inheritance hierarchy is implemented with TPH.

Here are entity mapping conditions:

  • __disc__ = car for Car
  • __disc__ = motorbike for Motorbike
  • __disc__ = bicycle for Bicycle

    How can I derive another child from Vehicle like MotorVehicle with following mapping condition:

  • __disc__ = car OR motorbike for MotorVehicle

I'd view in Database like this when I had this structure with TPT:

SELECT    Id
FROM      Vehicles
WHERE     (__Disc__ = N'car') OR (__Disc__ = N'motorbike')

I think this view is not required with TPH.

Please note that I can not change the inheritance like this: Vehicle<-- MotorVehicle<-- Car. Don't think about injecting the motor vehicles as the parent of car and other children because Car and Motorbike and Bicycle are already exists. I just want to assign some business to all motor vehicles.


Solution

  • Why couldn't you introduce a MotorVehicle level in the class hierarchy? You can. It's just an abstract class, so it doesn't need a discriminator value. EF hardly notices the class!

    I tried both with and without the MotorVehicle class and the database structure and the number of defined discriminators was the same in both cases.


    Edit

    This is what I did:

    public abstract class Vehicle
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    public abstract class MotorVehicle : Vehicle
    {
        public int Hp { get; set; }
    }
    
    public class Car : MotorVehicle
    { }
    
    public class MotorBike : MotorVehicle
    { }
    
    public class Bicycle : Vehicle
    { }
    
    internal class NestedInheritanceContext : DbContext
    {
        public DbSet<Vehicle> Vehicles { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Vehicle>().Property(v => v.Name).IsRequired();
            modelBuilder.Entity<Car>().Map(m => m.Requires("Discriminator")
                .HasValue("car").HasColumnType("char")
                .HasMaxLength(10)
                .IsRequired());
            modelBuilder.Entity<MotorBike>().Map(m => m.Requires("Discriminator")
                .HasValue("motorbike"));
            modelBuilder.Entity<Bicycle>().Map(m => m.Requires("Discriminator")
                .HasValue("bicycle"));
            base.OnModelCreating(modelBuilder);
        }
    }