Search code examples
c#.netasp.net-coreentity-framework-coreef-fluent-api

Entity Framework Core; how to use a many-to-many table's composite key as a foreign key?


This is my first question on the website, so if something seems off or the syntax isn't quite right, please let me know!

The schema below allows a player to join a profile using the many-to-many table profile-player.

SQL Diagram Schema

The table profile-player contains a composite key for player and profile using their associated primary keys. This allows players to be part of 0 or more profiles and a profile to contain 0 or more players.

This works fine, but when normalizing the data and expanding it into something like profile-player-inventory, it's using the primary keys of the profile and player table when I want it to use the composite keys from the profile-player table. I need it to use the composite key from the profile-player as it will cascade delete other rows such as in profile-player-inventory when the relationship is broken.

I've tried using the FluentAPI that EF Core provides to set its relationship, but I don't see any setting to physically change it to use the profile-player table's foreign key. It only allows me to set it to the profile or player table as shown below.

public sealed class ProfilePlayerInventoryConfiguration : IEntityTypeConfiguration<ProfilePlayerInventoryEntity>
{
    public void Configure(EntityTypeBuilder<ProfilePlayerInventoryEntity> builder)
    {
        builder.ToTable("profile_player_inventory");

        builder.HasKey(x => new { x.PlayerId, x.ProfileId });

        builder.HasOne(x => x.Profile).WithMany(x => x.ProfilePlayerInventorySet);
        builder.HasOne(x => x.Player).WithMany(x => x.ProfilePlayerInventorySet);
    }
}

Solution

  • In the end, the fix was pretty straight forward.

    I decided to change my profile-player table to be an auto-incrementing key with the player-id and profile-id being unique indexes instead.

    The profile-player-inventory now references the profile-player as I wanted it to as in the picture attached.

    Solution