Use IEntityTypeConfiguration with a base entity

Collin M. Barrett picture Collin M. Barrett · Oct 27, 2017 · Viewed 11.2k times · Source

In EF Core 2.0, we have the ability to derive from IEntityTypeConfiguration for cleaner Fluent API mappings (source).

How can I extend this pattern to utilize a base entity? In the example below, how can I have a BaseEntityConfiguration to reduce duplication in LanguageConfiguration and MaintainerConfiguration, modifying properties that are in the BaseEntity only in the BaseEntityConfiguration? What would such a BaseEntityConfiguration look like; and how would it be used, if at all, in OnModelCreating()? See the TODOs in-code near the end of the example.

Example:

public abstract class BaseEntity
{
    public long Id { get; set; }
    public DateTime CreatedDateUtc { get; set; }
    public DateTime? ModifiedDateUtc { get; set; }
}

public class Language : BaseEntity
{
    public string Iso6392 { get; set; }
    public string LocalName { get; set; }
    public string Name { get; set; }
}

public class Maintainer : BaseEntity
{
    public string Email { get; set; }
    public string Name { get; set; }
}

public class FilterListsDbContext : DbContext
{
    public FilterListsDbContext(DbContextOptions options) : base(options)
    {
    }

    public DbSet<Language> Languages { get; set; }
    public DbSet<Maintainer> Maintainers { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //TODO: Possibly add something like BaseEntityConfiguration?
        modelBuilder.ApplyConfiguration(new LanguageConfiguration());
        modelBuilder.ApplyConfiguration(new MaintainerConfiguration());
    }
}

public class LanguageConfiguration : IEntityTypeConfiguration<Language>
{
    public void Configure(EntityTypeBuilder<Language> entityTypeBuilder)
    {
        //TODO: Move this to something like BaseEntityConfiguration?
        entityTypeBuilder.Property(b => b.CreatedDateUtc).HasDefaultValueSql("CURRENT_TIMESTAMP");
    }
}

public class MaintainerConfiguration : IEntityTypeConfiguration<Maintainer>
{
    public void Configure(EntityTypeBuilder<Maintainer> entityTypeBuilder)
    {
        //TODO: Move this to something like BaseEntityConfiguration?
        entityTypeBuilder.Property(b => b.CreatedDateUtc).HasDefaultValueSql("CURRENT_TIMESTAMP");
    }
}

Answer

Cake or Death picture Cake or Death · Oct 27, 2017

Something like this could work (untested)?

public abstract class BaseEntityTypeConfiguration<TBase> : IEntityTypeConfiguration<TBase>
    where TBase : BaseEntity
{
    public virtual void Configure(EntityTypeBuilder<TBase> entityTypeBuilder)
    {
        //Base Configuration
    }
}

public class MaintainerConfiguration : BaseEntityTypeConfiguration<Maintainer>
{
    public override void Configure(EntityTypeBuilder<Maintainer> entityTypeBuilder)
    {
        entityTypeBuilder.Property(b => b.CreatedDateUtc).HasDefaultValueSql("CURRENT_TIMESTAMP");
        base.Configure(entityTypeBuilder);
    }
}