title: Code First EF6 - Update Many-To-Many Relationship in MVC Web Application
body: <p>I have a many to many relationship between Courses and Ingredients, and a one-to-many relationship between Meals and Courses.</p>
  
  <pre><code>public MealContext _context = new MealContext();
  public IEnumerable&lt;Meal&gt; Meals { get { return  _context.Meals.Include("Courses"); } }
  public IEnumerable&lt;Course&gt; Courses { get { return   _context.Courses.Include("Ingredients"); } }
  public IEnumerable&lt;Ingredient&gt; Ingredients { get { return _context.Ingredients; }
  
  public class BaseEntity
  {
      public int Id { get; set; }
      public DateTime Created { get; set; }
      public DateTime Updated { get; set; }
  }
  
  public class Meal : BaseEntity
  {
      public string Name { get; set; }
      public List&lt;Course&gt; Courses { get; set; }
  }
  
  public class Course : BaseEntity
  {
      public string Name { get; set;}
      public Meal Meal { get; set; }
      [ForeignKey("Ingredients")]
      public List&lt;int&gt; IngredientIds { get; set; }
      public List&lt;Ingredient&gt; Ingredients { get; set; }
  }
  
  public class Ingredient : BaseEntity
  {
      public string Name { get; set; }
  }
  
  public bool AddMeal(ref Meal meal)
  {
      try
      {
          _context.Meals.Add(meal);
          foreach (var course in meal.Courses)
          {
              course.Created = DateTime.Now;
              course.Updated = DateTime.Now;
  
              _context.Courses.Add(course);
              if(course.Ingredients == null) { course.Ingredients = new List&lt;Ingredient&gt;(); }
              foreach (var ingredient in course.Ingredients)
              {
                  _context.Entry(ingredient).State = EntityState.Modified;
              }
          }
          meal.Created = DateTime.Now;
          meal.Updated = DateTime.Now;
          _context.SaveChanges();
          trans.Commit();
          return true;
      }
      catch (Exception ex)
      {
          Logger.Error(ex.Message + "\n" + ex.StackTrace);
          trans.Rollback();
          return false;
      }
  }        
  </code></pre>
  
  <p>On the meal create view, I can add courses to a meal, and add ingredients to a course.  Everything works as intended.</p>
  
  <p>However, when I attempt to edit a meal, none of the ingredient changes to courses are ever saved, and no exception is thrown.</p>
  
  <p>My view uses drop down lists generated in an editor template to populate the IngredientIds collection, and I have verified that the list is both populated and correct by the time it reaches my repository.</p>
  
  <p>I've tried loading each course object from the database, setting each value of the tracked object to the value of the untracked object using _context.Entry(dbCourse).CurrentValues.SetValues(course).</p>
  
  <p>I've tried loading the ingredients into a list from the database by Id (course.Ingredients = _context.Ingredients.Where(i => course.IngredientIds.Contains(i.Id));).</p>
  
  <p>I've tried flagging each ingredient using _context.Entry(ingredient).State = EntityState.Modified.</p>
  
  <p>Nothing I do seems to work, and I've gone through just about every StackOverflow post I can find on the topic (most of which boil down to one of the three solutions above).</p>
  
  <p>How do I get these relationships to save properly?</p>
  
  <p>Currently, my update function looks like this:</p>
  
  <pre><code>public bool UpdateMeal(ref Meal meal)
  {
      using (var trans = _context.Database.BeginTransaction())
      {
          try
          {
              meal.Updated = DateTime.Now;
              if (meal.Courses != null)
              {
                  foreach (var course in meal.Courses)
                  {
                      course.Updated = DateTime.Now;
                      if (course.IngredientIds != null &amp;&amp; course.IngredientIds.Count &gt; 0)
                      {
                          var newIngredients = _context.Ingredients.Where(i =&gt; course.IngredientIds.Contains(i.Id)).ToList();
                          course.Ingredients = newIngredients;
                      }
                      var dbCourse = _context.Courses.Include("Ingredients").Single(c =&gt; c.Id == course.Id);
                      _context.Entry(dbCourse).CurrentValues.SetValues(course);
                  }
              }
              _context.SaveChanges();
              trans.Commit();
              return true;
          }
          catch (Exception ex)
          {
              Logger.Error(ex.Message + "\n" + ex.StackTrace);
              trans.Rollback();
              return false;
          }
      }
  }
  </code></pre>