Search code examples
c#entity-frameworkmany-to-many

Entity Framework Many to Many Clear doesnt Detach?


EF 6.1.3

I have an entity called DietPlan. It has a Many to Many relationship with Meals. There is a use case where a Diet Plan exists with a relational record to a meal already, and we want to add a new meal to that plan. I do this by DietPlan.Meals.Clear() then I call saveChanges (see code below), then I add the records that should be there, allowing for a delete and add in one shot.

What I find odd is that the meals that were part of the diet plan are still "attached" in memory somewhere, because if I try and call attach for the meal that was already existing, I get this error:

Attaching an entity of type 'XYZ.Data.Models.Meal' failed because another entity of the same type already has the same primary key value......

Code for DietPlan Entity:

public DietPlan()
{
    this.Meals = new List<Meal>();    
}
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Meal> Meals { get; set; }

Code for Meal Entity:

public Meal()
{
    this.DietPlans= new List<DietPlan>();    
}
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<DietPlan> DietPlans { get; set; }

Code for the Save:

public DietPlan Save(DietPlan record, List<Meal> addMeals)
{
    var contextEntry = this.DataContext.Entry(record); 


    if (contextEntry.State == EntityState.Detached)
    {
        this.DataContext.DietPlans.Attach(record);
    }

    if (record.ID > 0 && this.Find(record.ID) != null)
    {
        contextEntry.State = EntityState.Modified;
    }

    record.Meals.Clear();

    this.DataContext.SaveChanges();

    foreach(var meal in meals)
    {
        this.DataContext.Meals.Attach(meal); // THIS FAILS ON THE RECORD THAT WAS IN THIS COLLECTION BEFORE THE CLEAR()
    }

    this.DataContext.SaveChanges();
}

Why is this? Should I be calling another method to clear the collection that will also detach the entities?


Solution

  • If I understand well you first remove (clear) all the meals from a single DietPlan and then you add (attach) some meals to the context; in the contex still exists the meals you just removed from DietPlan and that could explain your error. The Clear method in this case dosen't detach the meals from context, but only mark the relation to be deleted when SaveChanges is going to be invoked. You have a many to many relation and you have a relation table between Diet and Meal in the underlying database. The clear mark (not really mark, but you can think like that) the records in this relation table and the records in this table participating to the relation will be deleted when SaveChanges is called.

    So from my point of view if you want to change the meals related to a DietPlan use Clear to remove all the meals from the DietPlan, then add the new meals to the Meal collection of the same DietPlan

    The result of invoking Clear or Remove is not always the same and depends from the type of relation involved. There are some case where the removed entity is effectively detached and deleted on SaveChange and others like this one where if you want to delete the entity you have to detach it before calling SaveChanges.