0

I have the following classes

public class Travel
{
    public int Id { get; set; }
    public string Location { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public List<Activity> Activities { get; set; }
    public List<ActivityTravel> ActivitityTravels { get; set; } = new List<ActivityTravel>();
}

public class Activity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<ActivityTravel> ActivitityTravels { get; set; } = new List<ActivityTravel>();
}

public class ActivityTravel
{
    public int TravelId { get; set; }
    public Travel Travel { get; set; }
    public int ActivityId { get; set; }
    public Activity Activity { get; set; }
}

My ApplicationDbContext looks like this

modelBuilder.Entity<ActivityTravel>()
        .HasKey(at => new { at.ActivityId, at.TravelId });

        modelBuilder.Entity<ActivityTravel>()
        .HasOne(at => at.Activity)
        .WithMany(a => a.ActivitityTravels)
        .HasForeignKey(at => at.ActivityId);

        modelBuilder.Entity<ActivityTravel>()
        .HasOne(at => at.Travel)
        .WithMany(t => t.ActivitityTravels)
        .HasForeignKey(at => at.TravelId);

    //outside of OnModelCreating
    public DbSet<Travel> Travels { get; set; }
    public DbSet<Activity> Activities { get; set; }
    public DbSet<ActivityTravel> ActivityTravels { get; set; }

A user can add a new Travel with a number of already existing Activites. But everytime a new Travel is added to the context, nothing is added to ActivityTravel. Here is the code used to add a new Travel

    public async Task<ActionResult> AddTravel([FromBody] Travel travel)
    {   
        travel.Activities.ForEach(a => travel.ActivitityTravels.Add(new ActivityTravel() { Activity = a, Travel = travel }));
        _context.Travels.Add(travel);

        //dont add activity again
        travel.Activities.ForEach(a => _context.Entry(a).State = EntityState.Detached);
        _context.SaveChanges();

        return Ok();
    }

I've followed the example in this question Saving many-to-many relationship in Entity Framework Core

Joshua H
  • 75
  • 1
  • 9
  • Have you tried without detach? If yes - try adding just `ActivitityTravels`: `_context.ActivityTravels.AddRange(travel.ActivitityTravels); _context.SaveChanges();` – Guru Stron Jun 18 '20 at 17:41
  • tried that, but then ef tries to add the activities which are already in the database and throws an exception – Joshua H Jun 18 '20 at 19:01
  • 1
    Ohh, you can receive already existing stuff. Then you need to [attach](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.attach?view=efcore-3.1) them first. – Guru Stron Jun 18 '20 at 19:12
  • Detaching was the problem and attaching them first helped. Thanks! – Joshua H Jun 18 '20 at 19:38
  • Will add as an answer then. – Guru Stron Jun 18 '20 at 19:49

1 Answers1

1

You should not detach your existing Activities you need to attach them first before handling other stuff, so they will not be added as duplicates. Something like this:

public async Task<ActionResult> AddTravel([FromBody] Travel travel)
{   
    travel.Activities.ForEach(a => travel.ActivitityTravels.Add(new ActivityTravel() { Activity = a, Travel = travel }));
    _context.AttachRange(travel.Activities);
    _context.Travels.Add(travel);
    _context.SaveChanges();
    return Ok();
}
Guru Stron
  • 102,774
  • 10
  • 95
  • 132