Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating composite primary key consisting off foreign keys in fluent API with ASP.NET core

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;
        }
    }
}
like image 230
Nyranith Avatar asked Feb 16 '17 08:02

Nyranith


People also ask

How do you set composite primary key in fluent API?

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.

Can foreign key reference composite primary key?

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.

Can two foreign keys make a composite key?

With intersection tables, it is common practice to make both of the foreign keys the composite primary key of the table.

Can foreign key constraint be composite?

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.


1 Answers

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.

like image 68
Smit Avatar answered Sep 23 '22 23:09

Smit