Entity Framework Migration Inheritance without creating the parent table

c# entity-framework-6 sql-server

Question

I have database objects that all inherit from a parent class with some base properties.

Base Entity

public abstract class Entity : IAuditable
{
    public int Id { get; set; }
    public string CreatedBy { get; set; }
    public int? CreatedDate { get; set; }
    public string UpdateBy { get; set; }
    public int? UpdatedDate { get; set; }
}

Base Entity Configuration file

public EntityConfiguration()
{
    HasKey(e => e.Id);

    Property(e => e.Id)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

    Property(e => e.CreatedBy)
        .IsUnicode(false)
        .HasMaxLength(255);

    Property(e => e.UpdatedBy)
        .IsUnicode(false)
        .HasMaxLength(255);
}

I subclass entity on all the child classes to inherit the common properties

public class User : Entity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

DbContext

public class SomeContext : DbContext
{
    public SomeContext() : base("name=DefaultConnection")
    {
    }

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

    public DbSet<Collaboration> Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new EntityConfiguration());
        modelBuilder.Configurations.Add(new UserConfiguration());
    }
}

When I create the migrations It will create all the inherited properties correctly but it still creates the parent class (Entity) even though I don't have a DbSet. If I remove the line that adds the configuration settings in the OnModelCreating method I don't get the max lengths and Unicode settings.

Is there a way to use the configuration properties without actually creating the parent table and without adding the configurations to all the subclass configuration files.

1
1
7/31/2018 3:33:22 PM

Accepted Answer

If anyone is interested here are the two solutions that I came up with. I opted for the second one as it seems to be the more accurate solution.

Solution 1

Use the Types configuration to the base class and anything inheriting the base class will also inherit the configuration.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Types<Entity>().Configure(c =>
    {
        c.HasKey(e => e.Id);

        c.Property(e => e.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        c.Property(e => e.CreatedBy)
            .IsUnicode(false)
            .HasMaxLength(255);

        c.Property(e => e.UpdatedBy)
            .IsUnicode(false)
            .HasMaxLength(255);
    });

    modelBuilder.Configurations.Add(new UserConfiguration());
} 

Solution 2

Use a combination of Generics, Interfaces and Inheritance to create a base EntityTypeConfiguration class. Then have other entity type configurations classes inherit from it.

public interface IEntity
{
    int Id { get; set; }
}

public interface IAuditable
{
    string CreatedBy { get; set; }
    DateTime? CreatedDate { get; set; }
    string UpdatedBy { get; set; }
    DateTime? UpdatedDate { get; set; }
}

public class EntityConfiguration<T> : EntityTypeConfiguration<T> where T : class, IEntity, IAuditable
{
    public EntityConfiguration()
    {
        HasKey(e => e.Id);

        Property(e => e.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        Property(e => e.CreatedBy)
            .IsUnicode(false)
            .HasMaxLength(255);

        Property(e => e.UpdatedBy)
            .IsUnicode(false)
            .HasMaxLength(255);
    }
}
-1
8/6/2018 12:35:27 PM

Popular Answer

This approach of inheritance with EF Code first is the Table per Concrete Type TPC Hierarchy

In the link you can find all the logic with examples on how to implement it. I know I shouldn't provide links but check the link, it has everything :)

Examples, Code explanation, graphs and images. I think it is exactly what you need to understand the TPC.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow