Home > Software engineering >  EntityFramework Code-first migration ignoring [Key] and forcing composite key
EntityFramework Code-first migration ignoring [Key] and forcing composite key

Time:12-07

I'm trying to create an object with a Guid primary [Key] using [Key], but EntityFramework keeps forcing the creation of a composite key.

public class Challenge
{
    [Key] public Guid Id { get; set; }
    public Guid ChallengerId { get; set; }
    public Guid ChallengeeId { get; set; }
    [ForeignKey("ChallengerId")]
    public virtual Player Challenger { get; set; }
    [ForeignKey("ChallengeeId")]
    public virtual Player Challengee { get; set; }
    public DateTime Initiated { get; set; }
}

and its migration...

migrationBuilder.CreateTable(
                name: "Challenges",
                columns: table => new
                {
                    ChallengerId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
                    ChallengeeId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
                    Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
                    Initiated = table.Column<DateTime>(type: "datetime2", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Challenges", x => new { x.ChallengerId, x.ChallengeeId });
                    table.ForeignKey(
                        name: "FK_Challenges_Players_ChallengeeId",
                        column: x => x.ChallengeeId,
                        principalTable: "Players",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_Challenges_Players_ChallengerId",
                        column: x => x.ChallengerId,
                        principalTable: "Players",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

Note that I've created the Player class using the same methodology, and EntityFramework respects the [Key] attribute there.

public class Player
{
    [Key] public Guid Id { get; set; }
    public string UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual IdentityUser User { get; set; }
    
    public virtual ICollection<Game> Games { get; set; }
    [InverseProperty("Challenger")]
    public virtual ICollection<Challenge> OutgoingChallenges { get; set; }
    [InverseProperty("Challengee")]
    public virtual ICollection<Challenge> IncomingChallenges { get; set; }
}
migrationBuilder.CreateTable(
                name: "Players",
                columns: table => new
                {
                    Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
                    UserId = table.Column<string>(type: "nvarchar(450)", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Players", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Players_IdentityUser_UserId",
                        column: x => x.UserId,
                        principalTable: "IdentityUser",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                });

Even when I go into the migration and change

table.PrimaryKey("PK_Challenges", x => new { x.ChallengerId, x.ChallengeeId });

to

table.PrimaryKey("PK_Challenges", x => x.Id);

EntityFramework seems to be struggling, as it creates Challenges in the SQL database with a composite key.

I'm using .NET 6.

CodePudding user response:

Might you be missing [Key] attribute in your Player model?

public class Player
{
    //Here should be a [Key] annotation
    public Guid Id { get; set; }
    public string UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual IdentityUser User { get; set; }
    
    public virtual ICollection<Game> Games { get; set; }
    [InverseProperty("Challenger")]
    public virtual ICollection<Challenge> OutgoingChallenges { get; set; }
    [InverseProperty("Challengee")]
    public virtual ICollection<Challenge> IncomingChallenges { get; set; }
}

CodePudding user response:

I found the guilty culprit: AppDbContext.cs

modelBuilder.Entity<Challenge>()
                    .HasForeignKey(c => new { c.ChallengerId, c.ChallengeeId });
  • Related