Search code examples
entity-frameworklinqinheritancelinq-to-entities

Add TPT Inherited Code First Model to Linq Fluent API


I'm having problems extending the Fluent API to my inheritance classes. I have taken the TPT (table per type) method and each type of the inheritance has a table. I like table per type because the database is fully normalized and easy to maintain. I am not getting the inherited model ServiceCompany to work with the Fluent API.

Base Abstract Class

public abstract class Vendor
{
    [Key]
    public int VendorID { get; set; }

    [Required]
    public string CompanyName { get; set; }

    [Required]
    public int StreetNumber { get; set; }

    [Required]
    public string StreetName { get; set; }
}

Inherited ServiceCompany Class from Vendor

[Table("ServiceCompanies")]
public class ServiceCompany : Vendor
{
    public string ACHClaim { get; set; }

    public virtual ICollection<SubContractorCompany> SubContractorCompanies { get; set; }

    public virtual ICollection<ServiceCompanyUser> SubContractorUsers { get; set; }
}

Where I added the entity models to enable the Fluent API with onModelCreating()

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
     public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public DbSet<Vendor> Vendors { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<ServiceCompany>().ToTable("ServiceCompanies");
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

I would like to be able to do something like this with the fluent API.

var ListofServiceCompanies = db.ServiceCompanies.All()

and not like this

var ListofServiceCompanies = db.Vendor.SelectMany( Vendor is a ServiceComapny...etc)

I prefer to set up the entities correctly and make the code nice and easy to use. Any insight or knowledge is appreciated.


Solution

  • You can do that by calling OfType extension method like below:

    var ListofServiceCompanies = db.Vendor.OfType<Vendor>().ToList();
    

    Or you can just add a DbSet<ServiceCompany> ServiceCompanies { get; set; } into your DbContext so it will look like this:

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
         public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }
    
        public DbSet<Vendor> Vendors { get; set; }
    
        public DbSet<ServiceCompany> ServiceCompanies { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<ServiceCompany>().ToTable("ServiceCompanies");
        }
    
        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    }
    

    Then just call:

    var ListofServiceCompanies = db.ServiceCompanies.ToList();