I am having troubles implementing a table-per-hierarchy architecture in combination with a one-to-one relation in EF 6 code-first and SQL-Server. Entity Framework doesn't use the right column as foreign key.
I have a class Version
and two inheriting classes ProductVersion
and FeatureVersion
.
public class Version
{
[Key]
public Int32 ID { get; private set; }
public Int32 Major { get; private set; }
public Int32 Minor { get; private set; }
public Int32 Patch { get; private set; }
..
}
The two inheriting classes implement nothing but the navigation properties.
public class ProductVersion : Version
{
[Required]
public virtual Product.Product Product { get; set; }
public Int32 ProductId { get; set; }
}
public class FeatureVersion : Version
{
[Required]
public virtual Feature Feature { get; set; }
public Int32 FeatureId { get; set; }
}
Now in my product I use a one-to-many relation and everything works fine.
public class Product
{
public Int32 ID { get; set; }
public String Name { get; set; }
public List<Versioning.ProductVersion> ProductVersions { get; set; }
...
}
In my feature I use a one-to-one relation and things get wrong.
public class Feature : ICloneable
{
public Int32 Id { get; set; }
...
public int FeatureVersionId { get; set; }
public virtual Entities.Versioning.FeatureVersion FeatureVersion { get; set; }
...
}
The resulting migration looks like this
CreateTable(
"dbo.Versions",
c => new
{
ID = c.Int(nullable: false),
...,
FeatureId = c.Int(),
ProductId = c.Int(),
Discriminator = c.String(nullable: false, maxLength: 128),
})
.PrimaryKey(t => t.ID)
.ForeignKey("dbo.Features", t => t.ID)
.ForeignKey("dbo.Products", t => t.ProductId, cascadeDelete: true)
.Index(t => t.ID)
.Index(t => t.ProductId);
As you see the foreign key to Features is using the wrong column.
When I change t => t.ID
manually to t => t.FeatureId, cascadeDelete: true
the foreign key gets inserted correctly into the database, but EF seems to have a problem inserting new features with an initial FeatureVersion
; the new FeatureVersion
's FeatureId
column is always set to 0 and therefore leading to an exception (in the code I simply assign a new FeatureVersion
object to the Feature object and try to save the context changes).
Everything works fine for Product with its one-to-many relation.
Interestingly when I change the reference in Feature from
public List<Versioning.ProductVersion> ProductVersions { get; set; }
to
public List<Versioning.Version> Versions { get; set; }
e.g. the mother class, everything works fine; in the migration I see the right columns joined and the INSERT works as well. But definitely, this is not what I want.
Is the inheritance somehow irritating EF? Am I missing an important point?
I also tried to change to relation for FeatureVersion
to a one-to-many relation same as for Product
. It works fine but this isn't the relation I need to use.