简体   繁体   中英

Creating a one to many with an association table in Entity Framework

I have an association table called SportTeams :

public class SportTeam
{
        int SportId;
        int TeamId;
        Sport Sport;
        Team Team
}

public class Sport
{
    ICollection<SportTeam> SportTeams;
}

public class Team
{
    ICollection<SportTeam> SportTeams;
}

I mark this as an association table via fluent api

modelBuilder.Entity<SportTeam>().HasKey(q => new { q.SportId,q.TeamId }); // set the primary key of the table
modelBuilder.Entity<SportTeam>().HasRequired(s => s.Team).WithMany(t => t.SportTeams).HasForeignKey(s => s.TeamId);
modelBuilder.Entity<SportTeam>().HasRequired(s => s.Sport).WithMany(s => s.SportTeams).HasForeignKey(s => s.SportId);

Now I need to create a one to many with the association table SportTeams . Let's call that table Matches .

public class Matches
{
    int Id;
    int SportTeamId;
    SportTeam SportTeam;
}

public class SportTeam
{
    int SportId ;
    int TeamId;
    Sport Sport;
    Team Team;

    ICollection<Match> Matches;
}

I go back to the fluent api to make the changes for this one to many.

I say

modelBuilder.Entity<SportTeam>().HasMany(st => st.Matches).WithRequired(matches => matches.SportTeam).HasForeignKey(m => m.SportTeamId).WillCascadeOnDelete(false);

I get an error:

The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical.

I believe this error states that my sportTeam PK is a composite key and in my HasForeignKey section I just specify one FK to connect with.

How should I go about this situation?

You're configuring the relashionship between SportTeam and Matches incorrectly. So you say that SportTeam entity can have many Matches then it logic that Matches entity to have a foreign key that reference the SportTeam entity.

But if your look at your SportTeam entity configuration, you say it has a composite keys as primary key ( SportId , TeamId ).

You get this error:

The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical.

Because if you have composite key as primary key then the foreign key that refers to the primary key of SportTeam should also have both the properties implied in the composite key.

So to solve this, your Matches entity should look like this:

public class Matches
{
    public int Id  { get; set; }

    // these two properties below represent the foreign key that refers to SportTeam entity.
    public int SportId { get; set; }
    public int TeamId { get; set; }

    public SportTeam SportTeam { get; set; };
}

In the OnModelCreating method you should have this line:

modelBuilder.Entity<SportTeam>()
            .HasMany(st => st.Matches)
            .WithRequired(matches => matches.SportTeam)
            .HasForeignKey(m => new { m.SportId, m.TeamId }) // <-- the composite foreign keys.
            .WillCascadeOnDelete(false);

Instead of:

modelBuilder.Entity<SportTeam>()
            .HasMany(st => st.Matches)
            .WithRequired(matches => matches.SportTeam)
            .HasForeignKey(m => m.SportTeamId)
            .WillCascadeOnDelete(false);

Side Note 1:

I always avoid using composite foreign key. If I end up with things like you have in your sample I just put a primary key property Id in SportTeam entity and make the couple of properties SportId and TeamId with unique constraint in database.

Side Note 2:

I don't know if you code like this in your real project but please use properties and make them public if necessary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM