The question here is how can i generate a composite primary key consisting of two foreign keys?
I have tried:
public class ActiveQuestions_Questions
{
[Column(Order = 0), Key, ForeignKey("ActiveQuestion")]
public string ActiveQuestionId {get; set;}
[Column(Order = 1), Key, ForeignKey("Question")]
public string QuestionId {get; set; }
}
Which gives me: Entity type 'ActiveQuestions_Questions' has composite primary key defined with data annotations. To set composite primary key, use fluent API.
Then i tried using the fluent api in the model builder without the annotations.
builder.Entity<ActiveQuestions_Questions>(
build =>
{
build.HasKey(t => new {t.ActiveQuestionId, t.QuestionId});
build.HasOne(t => t.QuestionId).WithOne().HasForeignKey<Question>(qe => qe.QuestionId);
build.HasOne(t => t.ActiveQuestionId).WithOne().HasForeignKey<ActiveQuestion>(qe => qe.ActivateQuestionId);
}
);
Which gave me : The navigation property 'QuestionId' cannot be added to the entity type 'ActiveQuestions_Questions' because a property with the same name already exists on entity type 'ActiveQuestions_Questions'.
Anyone that can point me in the right direction?
The Questions class
public class Question
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string QuestionId {get; set;}
[Required]
public string Text {get; set;}
}
The ActiveQuestion class:
public class ActiveQuestion
{
private DateTime _lastUpdated = DateTime.Now;
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string ActivateQuestionId {get; set;}
public DateTime LastUpdated
{
get
{
return this._lastUpdated;
}
set
{
this._lastUpdated = value;
}
}
}
Composite keys are not covered by conventions or data annotation attributes. The only way to configure composite keys is to use the HasKey method. You specify the properties that form the composite key by passing them in as properties of an anonymous type to the HasKey method.
This is not possible. The foreign key can not refer to part of composite primary key of other table. Because it is supposed to be one-to-one relationship and if you refer just part of primary-key, there might be more than one parent record available, which is neither allowed nor possible.
With intersection tables, it is common practice to make both of the foreign keys the composite primary key of the table.
A composite key specifies multiple columns for a primary-key or foreign-key constraint. The next example creates two tables. The first table has a composite key that acts as a primary key, and the second table has a composite key that acts as a foreign key.
In EF Core, defining composite PK using KeyAttribute
is not supported, therefore you must use fluent API to configure composite PK.
build.HasKey(t => new {t.ActiveQuestionId, t.QuestionId});
Above syntax you used in your code is correct way to define composite PK. For more information see Keys in docs.
The reason your code fails is the incorrect configuration of relationship. HasOne
/WithOne
API are supposed to be used with navigation properties (properties which targets other entity types). In your configuration you are passing a primitive property in HasOne
call. Since there is already property with same name added in the model (through conventions & HasKey
call), it throws above exception. Even if they hadn't been added, there would be different exception. Here is the link to docs on how to define relationships using fluent API.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With