Search code examples
c#.netentity-frameworkef-code-firstcode-first

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


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

I have the following Model

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; }
}

And configuration:

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);
    }
}

When I try and initialise the database via the update-database command in the package manager console I get the following error.

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.


Solution

  • I did a bit of testing to verify my comment and it worked.

    Your problem is that you have your FK - Design_Id - defined in base class, and navigation property for this Design defined in derived class. This way it's possible to have your FK Design_Id to be mapped incorrectly and allow it to be used as FK for multiple tables. To prevent these kinds of issues, Entity Framework says to you: put your FK property and Navigation property into same class. Otherwise, it will not work.

    So solution is to make your class structure like this:

    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; }
    }