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 tryin
You can use base class properties as foreign key associations as long as the principal also uses navigation properties of type base class.
The Principal (Version
) has declared ListOfSER
as navigation property of type SER
as Dependent
public class Version : BaseObject
{
public virtual ICollection<SER> ListOfSER { get; set; }
}
, but the configuration uses base class property (VersionId
) as foreign key association
public class VersionConfiguration : BaseObjectConfiguration<Version>
{
public VersionConfiguration()
: base()
{
HasMany(mdv => mdv.ListOfSER)
.WithRequired()
.HasForeignKey(ser => ser.VersionId) // -> belongs to base class
.WillCascadeOnDelete(false);
}
}
Which is not allowed when configuring ForeignKeyConstraintConfiguration, take a look at the code excerpt
foreach (var dependentProperty in dependentPropertyInfos)
{
var property
= dependentEnd.GetEntityType() // -> SER
.GetDeclaredPrimitiveProperty(dependentProperty); // -> VersionId
if (property == null) // VersionId is not part of SER metamodel
{
throw Error.ForeignKeyPropertyNotFound(
dependentProperty.Name, dependentEnd.GetEntityType().Name);
}
dependentProperties.Add(property);
}
The solution 1 would be changing the ListOfSER
type from SER
into AbstractR
.
public class Version : BaseObject
{
public virtual ICollection<AbstractR> ListOfSER { get; set; }
}
This will make more sense, the VersionId
is defined on base class, any derived type should be able to use this foreign key association, right? But unfortunately the Version
type only allows SER
to be associated with Version
.
You also have inconsistency when defining fluent api configuration.
public class VersionConfiguration : BaseObjectConfiguration<Version>
{
public VersionConfiguration()
: base()
{
HasMany(mdv => mdv.ListOfSER)
.WithRequired() // -> this should be WithRequired(x => x.Version)
.HasForeignKey(ser => ser.VersionId)
.WillCascadeOnDelete(false);
}
}
public class AbstractRConfiguration : BaseObjectConfiguration<AbstractR>
{
public AbstractRConfiguration()
: base()
{
HasRequired(ar => ar.Version)
.WithMany() // -> this should be WithMany(x => x.ListOfSER)
.HasForeignKey(ar => ar.VersionId)
.WillCascadeOnDelete(false);
}
}
Even more, you don't have to configure on both side. Just put it either on VersionConfiguration
or AbstractRConfiguration
would be sufficient.
The solution 2 would be moving the Version
and VersionId
from base class to SER
, if you want Version
only to be associated with SER
.
public class Version : BaseObject
{
public virtual ICollection<SER> ListOfSER { get; set; }
}
public abstract class AbstractR : BaseObject
{
}
public class SER : AbstractR
{
public int VersionId { get; set; }
public virtual Version Version { get; set; }
}
And configuring either on Version
configuration or SER
configuration.
public class VersionConfiguration : BaseObjectConfiguration<Version>
{
public VersionConfiguration()
: base()
{
HasMany(mdv => mdv.ListOfSER)
.WithRequired(x => x.Version)
.HasForeignKey(ser => ser.VersionId)
.WillCascadeOnDelete(false);
}
}
public class SERConfiguration : BaseObjectConfiguration<SER>
{
public SERConfiguration()
: base()
{
HasRequired(ar => ar.Version)
.WithMany(x => x.ListOfSER)
.HasForeignKey(ar => ar.VersionId)
.WillCascadeOnDelete(false);
}
}