简体   繁体   中英

Entity Framework many to many relationship insert

I have a Web API application with entity framework 6. I have 2 entities - Player and Match with many to many relationship between them:

 public class Player {
    public string PlayerId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public virtual ICollection<Match> Matches { get; set; }

}
 public class Match {
    public string MatchId { get; set; }
    public DateTime DateTime { get; set; }
    public virtual ICollection<Player> Players { get; set; }
}

This is how my DBContext looks like:

public class FIFA15RankingContext : DbContext {
    public DbSet<Player> Players { get; set; }
    public DbSet<Match> Matches { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<Player>()
            .HasMany(t => t.Matches)
            .WithMany(t => t.Players)
            .Map(m => {
                m.ToTable("PlayerMatches");
                m.MapLeftKey("PlayerId");
                m.MapRightKey("MatchId");
            }
            );
        base.OnModelCreating(modelBuilder);
    }
}   

EF created for me behind the scenes the table PlayerMatches (PlayerId, MatchId).

This is my MatchesController (as scaffolded by VS 2013):

    // POST: api/Matches
    [ResponseType(typeof(Match))]
    public async Task<IHttpActionResult> PostMatch(Match match)
    {
        if (!ModelState.IsValid)
           return BadRequest(ModelState);

        db.Matches.Add(match);

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateException)
        {
            if (MatchExists(match.MatchId))
               return Conflict();

            else
               throw;               
        }

        return CreatedAtRoute("DefaultApi", new { id = match.MatchId }, match);
    }

I want to be able to create new match and associate with it existing users. I couldn't make it work in any other way but to add this code (which smells pretty bad) before db.Matches.Add(match):

        var playersFromDB = new List<Player>();
        if (match.Players != null) {
            foreach (var p in match.Players) {
                playersFromDB.Add(db.Players.Find(p.PlayerId));
            }
        }
        match.Players = playersFromDB;

What am I doing wrong?

If all players already exists in database, you can attach them to dbcontext instead of load from db.

    if (match.Players != null) {
        foreach (var player in match.Players) {
            db.Players.Attach(player);
        }
    }

Manually attach the User entities and set their state to Unchanged

foreach( var p in match.Players )
{
    db.Entry( p ).State = EntityState.Unchanged;
}

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