Glebka
Glebka

Reputation: 1668

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.

Upvotes: 0

Views: 2365

Answers (2)

Jogge
Jogge

Reputation: 1852

If it makes sense, you should move the Design_Id property to the derived class, as in the answer from Red.

If it does not make any sense, you can just hide the inherited property using the new keyword:

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

This also gives you the advantage of being able to set up the mapping using the ForeingKey attribute.

Upvotes: 0

Red
Red

Reputation: 2776

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

Upvotes: 4

Related Questions