Entity Framework - 外键组件未在类型上声明 属性

Entity Framework - The foreign key component is not a declared property on type

public virtual DbSet<DBVolumetricObject> Volumetrics { get; set; } //this make error

我有以下型号

public abstract class DBVolumetricObject
{
    public int Id { get; set; }
    public int Design_Id { get; set; }
}

public class Material : DBVolumetricObject
{
    public virtual MaterialDesign MaterialDesign { get; set; }
}

public class MaterialDesign : IDBDesign
{
    ...
    public virtual List<Material> Materials { get; set; }
}

和配置:

public class MaterialConfiguration : EntityTypeConfiguration<Material>
{
    public MaterialConfiguration()
    {
        Map(m => m.MapInheritedProperties());

        HasRequired<MaterialDesign>(x => x.MaterialDesign)
            .WithMany(x => x.Materials)
            .HasForeignKey(x => x.Design_Id);
    }
}

当我尝试通过包管理器控制台中的更新数据库命令初始化数据库时,出现以下错误。

The foreign key component 'Design_Id' is not a declared property on type 'Material'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.

我做了一些测试来验证我的评论并且它有效。

您的问题是您的 FK - Design_Id - 在基础 class 中定义,并且此设计的导航 属性 在派生 class 中定义。这样,您的 FK Design_Id 可能会被错误映射并允许它用作多个表的 FK。为了防止这些问题,Entity Framework 告诉你:把你的 FK 属性 和导航 属性 放到同一个 class 中。不然不行。

所以解决方案是使您的 class 结构像这样:

public abstract class DBVolumetricObject
{
    public int Id { get; set; }
}

public class Material : DBVolumetricObject
{
    public int Design_Id { get; set; }
    public virtual MaterialDesign MaterialDesign{ get; set; }       
}

public class MaterialDesign : IDBDesign
{
   ...
   public virtual List<Material> Materials { get; set; }
} 

如果有意义,您应该将 Design_Id 属性 移动到派生的 class,如 from Red.

如果没有任何意义,您可以使用 new 关键字隐藏继承的 属性:

public abstract class DBVolumetricObject
{
    public int Id { get; set; }
    public int Design_Id { get; set; }
}

public class Material : DBVolumetricObject
{
    [ForeignKey(nameof(MaterialDesign))]
    public new int Design_Id { get; set; }
    public virtual MaterialDesign MaterialDesign { get; set; }
}

public class MaterialDesign : IDBDesign
{
    ...
    public virtual List<Material> Materials { get; set; }
}

这也让您能够使用 ForeingKey 属性设置映射。