Entity framework Fluent API does not consider base class properties

前提是你 提交于 2019-12-01 01:21:30

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);
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!