How to use foreign key as composite key in EF Core 2?

c# composite-primary-key ef-core-2.0 entity-framework-core foreign-keys

Question

I have several classes in EF Core 2. 1) Class Ser

  • has id as Guid type. It is a primary key, auto-incremented.

2) Class SerStaHis

  • has SerId as Guid type. It is a foreign key to Class Ser. It is a primary key with timestamp

  • has timestamp. It is a primary key with SerId

I use EF Core 2 to build two tables above. I have used Composite Key feature to combine SerStaHis.timestamp and SerStaHis.SerId as primary key.

I also use ForeignKey attribute in Class Ser. The problem is I have managed to map the foreign key to Class SerStaHis, but I could not combine that foreign key with SerStaHis.timestamp as a primary key.

Here are code snippets for Class Ser, Class SerStaHis and OnModelCreating method.

public class Ser {
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]   // auto-incrementing feature
    public Guid id { get; set; }

    //nav/foreign keys
    [ForeignKey("id")]
    public virtual ICollection<SerStaHis> SerStaHis{ get; set; }
}

public class SerStaHis{
    [Required] // maybe this is wrong as I got a foreign key from Class Ser
    public Guid service_id { get; set; }
    [Required]
    public DateTime timestamp { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder) {
        base.OnModelCreating(modelBuilder);

        // composite primary keys method. // https://docs.microsoft.com/en-us/ef/core/modeling/keys
        modelBuilder.Entity<SerStaHis>()
            .HasKey(c => new {c.service_id, c.timestamp});
    }

Here is the actual result I got when I migrate to SQL: actual result
(source: pbrd.co)

My expected result in SQL is as followed:expected result
(source: pbrd.co)

Please let me know if you need more clarification.

Can I do the task above in FluentAPI method?

How do I use the foreign key as composite primary key?

Thank you

1
1
10/28/2019 1:21:16 PM

Accepted Answer

Change

[ForeignKey("id")]
public virtual ICollection<SerStaHis> SerStaHis{ get; set; }

to

[ForeignKey("service_id")]
public virtual ICollection<SerStaHis> SerStaHis{ get; set; }

ForeignKey attribute works differently when applied on the FK property, reference navigation property and collection navigation property. When applied on collection navigation property, it specifies the FK property name of the related object.

I personally find ForeignKey attribute confusing and error prone. Fluent API is much more intuitive and provides much better control. The fluent configuration for your scenario is like this:

modelBuilder.Entity<Ser>()
    .HasMany(ser => ser.SerStaHis) // collection navigation property
    .WithOne() // no reference navigation property
    .HasForeignKey(serStaHis => serStaHis.service_id); // foreign key property
2
1/18/2019 12:28:24 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow