Search code examples
asp.net-mvcentity-framework-6

How to use table created using TPH in entity framework?


Domain Model

 public abstract class BaseClass
{
    public int Id { get; set; }
    public int Something1 { get; set; }
    public int Something2 { get; set; }
    public string Something3 { get; set; }
}

public class PQR1 : BaseClass
{
    public int value1 { get; set; }
}


public class PQR2 : BaseClass
{
    public int value2 { get; set; }
}


public class PQR3 : BaseClass
{
    public int value2 { get; set; }
}

Context Class

 public class PQRContext : DbContext
{
    public PQRContext() : base ("PQR")
    {

    }

    public DbSet<BaseClass> Baseclass { get; set; }




    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

      modelBuilder.Entity<BaseClass>().
          Map<PQR1>(m => m.Requires("Type").HasValue("Value1"))
          .Map<PQR2>(m => m.Requires("Type").HasValue("Value2"))
          .Map<PQR3>(m => m.Requires("Type").HasValue("Value3"));
    }
}

It'll create table like this:

enter image description here

But I don't know how to use this table while coding, I get stuck like this enter image description here

So I can't access to another classes like PQR1, PQR2,PQR3 where as I have no reason to insert data into base class which is already abstract.


Solution

  • First option :

    You are not restricted on DbSet creations. You can create many DbSet as much as you need for your derived classes like the code below and access them like you will do with other DbSet :

    public DbSet<BaseClass> Baseclass { get; set; }
    public DbSet<PQR1> PQR1s { get; set; }
    public DbSet<PQR2> PQR2s { get; set; }
    public DbSet<PQR3> PQR3s { get; set; }
    

    You use the DbSet related to the derived you want for inserting into or requesting your context.

    Second option :

    For querying your context and get only the desired subclass entities you can use the generic method OfType<T> which act as a filter like this:

    var myBaseClassList = myContext.BaseClass; // Retrieve all PQR1, PQR2 and PQR3 entities
    var myPQR1List = myContext.BaseClass.OfType<PQR1>(); // Retrieve all PQR1
    var myPQR2List = myContext.BaseClass.OfType<PQR2>(); // Retrieve all PQR2
    var myPQR3List = myContext.BaseClass.OfType<PQR3>(); // Retrieve all PQR3
    

    For inserting you can create an instance of your derived class and add it directly to your base class DbSet :

    var pqr1 = new PQR1() {  /* set my properties */ };
    myCOntext.BaseClass.Add(pqr1); // EF knows how to insert data for classes that use TPH.