5

I have a some error : EF 4: Removing child object from collection does not delete it - why?

when i remove a child from the parent that the child is deleted when i call SaveChanges(), it gives the follow error message:

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

But with DbContext and EF 4.1, the "context.DeleteObject(recipe)" does not exist.

Any suggestion ?

[EDIT]

    public void UpdateWithAttributes(Model model, IEnumerable<Entity> entities)
    {
        var modelOriginal = this.unitOfWork.Model.GetById(model.IModel);

        this.unitOfWork.Context.Entry(modelOriginal).CurrentValues.SetValues(model);
        UpdateEntityAttributeAssociations(modelOriginal, entities);

        this.unitOfWork.Commit();
    }

    public void UpdateEntityAttributeAssociations(Model model, IEnumerable<Entity> current)
    {
        unitOfWork.Context.Entry(model).Collection(m => m.Entities).Load();
ICollection<Entity> original = model.Entities; // perhaps .ToList() necessary

        // delete
        if (original != null)
        {
            List<Entity> toDelete = GetToDelete(original, current);

            foreach (Entity originalEntityToDelete in toDelete)
            {
                unitOfWork.Context.Entity.Remove(originalEntityToDelete);
            }
        }

        // add, update
        if (current != null)
        {
            foreach (Entity currentEntity in current)
            {
                // No need to set the UpdatedWhen. The trigger on the table will handle that.
                if (original.Where(originalEntity => originalEntity.IEntity == currentEntity.IEntity).FirstOrDefault() == null)
                {
                    model.Entities.Add(currentEntity);
                }
            }
        }
    }
Community
  • 1
  • 1
rad
  • 1,857
  • 1
  • 20
  • 30

2 Answers2

2

You have to call:

context.Recipes.Remove(recipe);

Where Recipes are DbSet<Recipe>.

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
1

I guess that you are adding again what you have just deleted because removing from the DbSet also removes internally the entity from the child collection original. Then in the second loop you add the entity again. You could try to catch this situation like so:

public void UpdateEntityAttributeAssociations(Model model,
                                              IEnumerable<Entity> current)
{
    unitOfWork.Context.Entry(model).Collection(m => m.Entities).Load();
    ICollection<Entity> original = model.Entities; // perhaps .ToList() necessary

    // delete
    List<Entity> toDelete = null;
    if (original != null)
    {
        toDelete = GetToDelete(original, current);
        foreach (Entity originalEntityToDelete in toDelete)
        {
            unitOfWork.Context.Entity.Remove(originalEntityToDelete);
        }
    }

    // add, update
    if (current != null)
    {
        foreach (Entity currentEntity in current)
        {
            if (toDelete == null || !toDelete.Contains(currentEntity))
            {
                if (original.Where(originalEntity => originalEntity.IEntity == 
                               currentEntity.IEntity).FirstOrDefault() == null)
                {
                    model.Entity.Add(currentEntity);
                }
            }
        }
    }
}

I've also replaced your first line with explicit loading the child collection since your procedure to query the child entities manually looks unfamiliar to me, but I don't think that this is the problem (but I don't know).

Edit

I'm not sure if my code above helps to remove the exception you had. I don't know what happens if you add an entity to a collection which is already in Deleted state and if this could throw this exception.

If the code doesn't help you could test if you also have the problem without the second (the Insert) loop. And how looks GetToDelete exactly? And how look your Model and Entity class and their relationships? And is model.Entity indeed another collection than model.Entities (or is it a typo)?

Slauma
  • 175,098
  • 59
  • 401
  • 420
  • Thank you Slauma for your reponse. With your code i have another error : The DELETE statement conflicted with the REFERENCE constraint {0}. The conflict occurred in database \"MyDatabase\", table \"{1}\", column '{2}'.\r\nThe statement has been terminated. – rad May 25 '11 at 17:57
  • @rad: I have no clue. You should edit answers to my last questions above into your question. There are too many missing informations to understand the problem in detail and to provide a working solution (at least for me). – Slauma May 25 '11 at 18:05
  • @rad: I would think there is another entity which refers to the entity you are just trying to delete. The secret content of `{0}`, `{1}` and `{2}` should give a rather important hint! – Slauma May 25 '11 at 18:14
  • I think the new problem is because another entity is referenced the deleted as slauma said, maybe you need some cascada delete to fix it – RJardines Sep 24 '12 at 22:26