Search code examples
c#entity-frameworkentity-framework-coreentity-framework-migrationsef-fluent-api

Composite Key EF Core getting error when using Fluent Api


So I have the following class in Entity Framework Core. I am trying to do a code first migration and can't for the life of me figure out how to make the fluent API for this work.

public class Participants
{
    public Activity Activity { get; set; } //Class with Id and Name of Activity
    public ApplicationUser Participant { get; set; } 

    [Key]
    [Column(Order = 1)]
    public int ActivityId { get; set; }


    [Key]
    [Column(Order = 2)]
    public string ParticipantId { get; set; }
}

In EF6 I was able to do this in OnModelCreating to get it to work fine.

 modelBuilder.Entity<Attendance>()
            .HasRequired(a => a.Activity)
            .WithMany()
            .WillCascadeOnDelete(false);

But in EF Core I get

" Entity type 'Participants' has composite primary key defined with data annotations. To set composite primary key, use fluent API."

I have tried using

modelBuilder.Entity<Participants>().HasKey(p => new {p.Activity, p.Participant});

But, that just leads to

Introducing FOREIGN KEY constraint 'FK_Participants_AspNetUsers_ParticipantId' on table 'Participants' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

If there is a better way to do the whole thing I'm open to suggestions. If you have pluralsight subscription, I'm basically trying to get "Become a Full Stack Developer" by Mosh Hamedani to work in EF core. The example is in "13-full-stack-fundamentals" folder.

UPDATE: Also tried

        modelBuilder.Entity<Participants>()
            .HasOne(p => p.Activity)
            .WithMany()
            .OnDelete(DeleteBehavior.Cascade);

Still got

"Entity type 'Participants' has composite primary key defined with data annotations. To set composite primary key, use fluent API."

UPDATE 2: After trying Roy's suggestion this is what I'm getting

Introducing FOREIGN KEY constraint 'FK_Participants_AspNetUsers_ParticipantId' on table 'Participants' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

UPDATE 3: In the Migration

I removed one of the OnDelete: ReferntialAction.Cascade and it worked. I removed the one off of FK_Participants_AspNetUsers_ParticipantId.

I also changed this in my OnModelCreating

        modelBuilder.Entity<Participants>()
            .HasKey(p => new { p.ActivityId, p.ParticipantId });
        base.OnModelCreating(modelBuilder);

        //Added this ( Not sure if it's needed if anyone knows let me know) 
        modelBuilder.Entity<Participants>()
            .HasOne(p => p.Activity)
            .WithMany()
            .OnDelete(DeleteBehavior.Cascade);

Solution

  • What you are trying to do is create a relationship between Activity and Participant which is a little different in EFCore.

    To do it, you would need to reference the ForeignKey Properties instead of NavigationProperties in the modelbuilder as follows:

        modelBuilder.Entity<Participants>()
            .HasKey(p => new { p.ActivityId , p.ParticipantId });