EF 6.1 :
We just started a project that has a lot pf inheritance. The selected inheritance db mapping type is the table per hierarchy. The problem is that when trying to generate the migration using the add-migration, the following error is thrown :
The foreign key component 'VersionId' is not a declared property on type 'SER'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.
Here are the classes & the configuration classes used :
public class Version : BaseObject
{
public virtual ICollection<SER> ListOfSER { get; set; }
}
public abstract class AbsractR : BaseObject
{
public int ParentId { get; set; }
public int ChildId { get; set; }
public int VersionId { get; set; }
public virtual Version Version { get; set; }
}
public class SER : AbstractR
{
public int SEDId
{
get
{
return base.ChildId;
}
set
{
base.ChildId = value;
}
}
public virtual SED SED { get; set; }
}
public abstract class AbstractD : BaseObject
{
}
public class SED : AbstractD
{
public virtual ICollection<SER> ListOfSER { get; set; }
}
public class SDContext : BaseContext
{
public DbSet<Version> Versions { get; set; }
public DbSet<AbstractD> Ds { get; set; }
public DbSet<AbstractR> Rs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new VersionConfiguration());
#region Refs
modelBuilder.Configurations.Add(new AbstractRConfiguration());
modelBuilder.Configurations.Add(new SERConfiguration());
#endregion
#region Defs
modelBuilder.Configurations.Add(new AbstractDConfiguration());
modelBuilder.Configurations.Add(new SEDConfiguration());
#endregion
}
}
public class BaseObjectConfiguration<T> : EntityTypeConfiguration<T> where T : BaseObject
{
public BaseObjectConfiguration()
{
#region Key
this.HasKey(bo => bo.Id);
#endregion
#region Properties
this.Property(bo => bo.Id).IsRequired();
this.Property(bo => bo.IsDeleted).IsRequired();
this.Property(bo => bo.LastModificationDate).IsOptional();
this.Property(bo => bo.OptimisticVersion).IsConcurrencyToken().IsRequired().IsRowVersion();
this.Property(bo => bo.CreationDate).IsRequired();
this.Property(bo => bo.DeletionDate).IsOptional();
#endregion
}
}
public class VersionConfiguration : BaseObjectConfiguration<Version>
{
public VersionConfiguration() : base()
{
#region Properties
#endregion
#region Objects
this.HasMany(mdv => mdv.ListOfSER).WithRequired().HasForeignKey(ser => ser.VersionId).WillCascadeOnDelete(false);
#endregion
#region Table
this.ToTable("Versions");
#endregion
}
}
public class AbstractRConfiguration : BaseObjectConfiguration<AbstractR>
{
public AbstractRConfiguration()
: base()
{
#region Properties
this.Property(ser => ser.VersionId).IsRequired();
#endregion
#region Objects
this.HasRequired(ar => ar.Version).WithMany().HasForeignKey(ar => ar.VersionId).WillCascadeOnDelete(false);
#endregion
#region Table
this.ToTable("Refs");
#endregion
}
}
public class SERConfiguration : BaseObjectConfiguration<SER>
{
public SERConfiguration()
: base()
{
#region Properties
this.Ignore(ser => ser.SEDId);
#endregion
#region Objects
this.HasRequired(ser => ser.SED).WithMany(sed => sed.ListOfSER).HasForeignKey(ser => ser.ChildId).WillCascadeOnDelete(false);
#endregion
#region Table
this.ToTable("Refs");
#endregion
}
}
public class AbstractDConfiguration : BaseObjectConfiguration<AbstractD>
{
public AbstractDConfiguration() : base()
{
this.ToTable("Defs");
}
}
public class SEDConfiguration : BaseObjectConfiguration<SED>
{
public SEDConfiguration()
: base()
{
#region Properties
#endregion
#region Objects
this.HasMany(sed => sed.ListOfSER).WithRequired(sed => sed.SED).HasForeignKey(sed => sed.ChildId).WillCascadeOnDelete(false);
#endregion
#region Table
this.ToTable("Defs");
#endregion
}
}
I know we can use the [ForeignKey] attribute to tell that the navigation property on a derived class should use the column defined in the parent abstract class. We would like to avoid using DataAnnotations. I just don't get why it throw this error. The "Version" navigation property is defined in the AbstractR configuration and not in the SER configuration (which should also work since SER inherits from AbstractR), am I right ?
Secondly, when removing the Version property & mapping, the same problem appears with the "ChildId" and "ParentId" property used in the SER mapping. Is this a know problem ? Am I doing something wrong ?
PS : The ParentId mapping has been removed for simplicity since it seems to be the same problem as the ChildId mapping.
Has anyone any idea why this kind of problem is happening ?
UPDATE
After some more research, it appeared that Fluent API cannot use base class properties for the mapping. Is that right ? Is this a wanted behavior ? Why are the DataAnnotations able to use base class properties and not Fluent API ? Aren't all the base class properties inserted inside every classes or is it read with some kind of decorator pattern ?