Reputation: 68
I'm having an issue with Entity Framework where I have something similar to the following mockup:
public class ClassA
{
public int ClassAID { get; set; }
}
public class ClassB
{
public int ClassBID { get; set; }
}
public class ClassC
{
public int ClassAID { get; set; } //Foreign Keys combined as Primary Key
public int ClassBID { get; set; }
public virtual ClassA SomeA { get; set; }
public virtual ClassB SomeB { get; set; }
public virtual ClassD SomeD { get; set; }
}
public class ClassD
{
public int ClassAID { get; set; } //Primary Key and also references Class C Primary Key
public int ClassBID { get; set; }
public virtual ClassC SomeC { get; set; }
}
ClassD is where I am having a problem, I want the properties that represent the primary key on ClassC to be the primary key on ClassD, but also be a foreign key reference. (Assume the property names above are the same as the table column names)
In the underlying database the corresponding tables for ClassC and ClassD have a one-to-one relationship, where as ClassA to ClassC and ClassB to ClassC is a one-to-many relationship.
When it comes to Entity Framework however it cannot seem to handle multiple properties of the same name acting as a primary key and foreign key at the same time, in the underlying SQL that it generates, I can see it looking for columns ClassD_ClassAID, ClassD_ClassBID - is there a way using the Model Configuration to specify the correct mapping?
I have tried:
this.HasKey(c => new { c.ClassAID, c.ClassBID });
this.HasRequired(c => c.ClassC)
.WithRequiredDependent();
I've also tried:
this.HasKey(c => new { c.ClassAID, c.ClassBID });
this.HasRequired(c => c.ClassC)
.WithRequiredDependent()
.Map(m => m.MapKey("ClassAID", "ClassBID"));
Any attempt so far to introduce a mapping is met with
'Property name xxx already exists in the metadata'.
Upvotes: 1
Views: 3592
Reputation: 177133
I am not sure if the following solves your problem because I don't understand where the exception you mentioned could come from:
modelBuilder.Entity<ClassC>()
.HasKey(c => new { c.ClassAId, c.ClassBId });
modelBuilder.Entity<ClassD>()
.HasKey(d => new { d.ClassAId, d.ClassBId })
.HasRequired(d => d.SomeC)
.WithRequiredDependent(c => c.SomeD);
The important part here is that you specify the navigation property on the other side of the relationship in WithRequiredDependent
. If you use the parameterless overload EF will create a second relationship between ClassC
and ClassD
and SomeD
would belong to this relationship and not to the one you are configuring.
I you don't specify any further mapping for ClassA
and ClassB
EF will create the following three relationships based on the mapping above and on conventions:
So, ClassD
has a composite primary key which is a composite foreign key to ClassC
at the same time.
Upvotes: 4