Reputation: 11348
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");
}
}
Upvotes: 6
Views: 5158
Reputation: 181
public class BaseEntityTypeConfiguration<T> : IEntityTypeConfiguration<T> where T : BaseEntity
{
public virtual void Configure(EntityTypeBuilder<T> entity)
{
entity.HasKey(e => e.Id);
}
}
public class NewsEntityTypeConfiguration : BaseEntityTypeConfiguration<News>
{
public override void Configure(EntityTypeBuilder<News> entity)
{
base.Configure(entity);
entity.ToTable("News");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new NewsEntityTypeConfiguration());
}
Upvotes: 0
Reputation: 25
Sorry I cannot comment but I would do as you are doing only swap these two lines around
modelBuilder.Configurations.Add( conf ); // this has base mapping now
var newsConf = new NewsConfiguration(conf); // now the Object specific properties stuff
to
new NewsConfiguration(conf); // now the Object
modelBuilder.Configurations.Add( conf ); // this has base mapping now
This helps EF with specialised fields.
Upvotes: 0
Reputation: 330
The answer above definitely works, though this may be slight cleaner and has the advantage of working the same when registering the configurations in the DbContext.
public abstract class BaseEntity
{
public int Id { get; set; }
}
public class Company : BaseEntity
{
public string Name { get; set; }
}
internal class BaseEntityMap<T> : EntityTypeConfiguration<T> where T : BaseEntity
{
public BaseEntityMap()
{
// Primary Key
HasKey(t => t.Id);
}
}
internal class CompanyMap : BaseEntityMap<Company>
{
public CompanyMap()
{
// Properties
Property(t => t.Name)
.IsRequired()
.HasMaxLength(256);
}
}
public class AcmeContext : DbContext
{
public DbSet<Company> Companies { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new CompanyMap());
}
}
Above solution arrived at by Christian Williams and myself early one morning...
Upvotes: 9
Reputation: 11348
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");
}
}
Upvotes: 3