Search code examples
c#ef-code-first

Abstract domain model base class when using EntityTypeConfiguration<T>


Is there some trick to getting a central mapping of Base object properties? Is there some simple pattern for abstract classes when using EntityTypeConfiguration.
ANy tips much appreciated. Im unable to declare a class

Public class BaseEntityConfig<T> : EntityTypeConfiguration<T>

Similar issues, where i couldnt get the answers to work How to create and use a generic class EntityTypeConfiguration<TEntity> and Dynamic way to Generate EntityTypeConfiguration : The type 'TResult' must be a non-nullable value type

public  abstract class BosBaseObject
{
  public virtual Guid Id { set; get; }
  public virtual string ExternalKey { set; get; }
  public byte[] RowVersion { get; set; }
}
  public class News : BosBaseObject
{
    public String Heading { set; get; }
}


public class NewsMap : EntityTypeConfiguration<News>
{
    public NewsMap()
    {
      //Base Object Common Mappings
      // How can we use a central mapping for all Base Abstract properties  


     }
 }
// Something like this but very open to any suggestion....
public class BosBaseEntityConfig<T> : EntityTypeConfiguration<T>
{
  public void BaseObjectMap( )
    { 
        // Primary Key
        this.HasKey(t => t.Id);

        // Properties
        this.Property(t => t.Id).HasDatabaseGeneratedOption(databaseGeneratedOption: DatabaseGeneratedOption.None);

        this.Property(t => t.RowVersion)
            .IsRequired()
            .IsFixedLength()
            .HasMaxLength(8)
            .IsRowVersion();

        //Column Mappings
        this.Property(t => t.Id).HasColumnName("Id");
    }
}

Solution

  • After 6 hrs I cracked it. I think it is a reasonably clean outcome. The trick is to forget doing every inside a class derived from EntityTypeConfiguration and build a custom BaseConfig and then to take this instance and add the specifics for this class. Hope it helps others doing code first with abstracts...

    public  abstract class BosBaseObject
    {
      public virtual Guid Id { set; get; }
      public virtual string ExternalKey { set; get; }
      public byte[] RowVersion { get; set; }
    }
     public abstract class BosObjectDateManaged   :  BosBaseObject
    {
        public DateTimeOffset ValidFrom { set; get; }
        public DateTimeOffset ValidTo { set; get; }
    }
    public class News : BosObjectDateManaged
    {
        public String Heading { set; get; }
    }
    
    
    
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            var conf = new BosBaseEntityConfiguration<News>();//Construct config for Type
            modelBuilder.Configurations.Add( conf );  // this has base mapping now
            var newsConf = new NewsConfiguration(conf); // now the Object specific properties stuff
    
        }
    
    }
    public class BosBaseEntityConfiguration<T> : EntityTypeConfiguration<T> where T : BosBaseObject
    {
       public BosBaseEntityConfiguration()
       {
           // Primary Key
           this.HasKey(t => t.Id);
    
           //// Properties
           this.Property(t => t.Id).HasDatabaseGeneratedOption(databaseGeneratedOption: DatabaseGeneratedOption.None);
    
           this.Property(t => t.RowVersion)
               .IsRequired()
               .IsFixedLength()
               .HasMaxLength(8)
               .IsRowVersion();
    
           //Column Mappings
           this.Property(t => t.Id).HasColumnName("Id");
       }
    }
     public class NewsConfiguration  
    {
        public  NewsConfiguration(BosBaseEntityConfiguration<News> entity)
        {
            // Table Specific & Column Mappings
            entity.ToTable("News2");
            entity.Property(t => t.Heading).HasColumnName("Heading2");
        }
    }