EF 4.1: Удаление дочернего объекта из коллекции не удаляет его - почему? - PullRequest
5 голосов
/ 25 мая 2011

У меня ошибка: EF 4: удаление дочернего объекта из коллекции не приводит к его удалению - почему?

когда я удаляю ребенка от родителя, который удаляется при вызове SaveChanges(), выдается следующее сообщение об ошибке:

Операция завершилась неудачно: отношение не может быть изменено, поскольку одно или несколько свойств внешнего ключа не могут быть равны нулю. Когда в отношение вносится изменение, для соответствующего свойства внешнего ключа устанавливается нулевое значение. Если внешний ключ не поддерживает нулевые значения, необходимо определить новое отношение, свойству внешнего ключа должно быть назначено другое ненулевое значение или несвязанный объект должен быть удален.

Но с DbContext и EF 4.1 "context.DeleteObject (recipe)" не существует.

Есть предложения?

[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);
                }
            }
        }
    }

Ответы [ 2 ]

2 голосов
/ 25 мая 2011

Вы должны позвонить:

context.Recipes.Remove(recipe);

Где Recipes DbSet<Recipe>.

1 голос
/ 25 мая 2011

Полагаю, вы снова добавляете то, что только что удалили, потому что удаление из DbSet также удаляет сущность из дочерней коллекции original. Затем во втором цикле вы снова добавляете объект. Вы можете попытаться уловить эту ситуацию следующим образом:

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);
                }
            }
        }
    }
}

Я также заменил вашу первую строку явной загрузкой дочерней коллекции, поскольку ваша процедура запроса дочерних сущностей вручную выглядит мне незнакомой, но я не думаю, что это проблема (но я не знаю) .

Редактировать

Я не уверен, поможет ли мой код выше удалить исключение, которое вы имели. Я не знаю, что произойдет, если вы добавите объект в коллекцию, которая уже находится в состоянии Deleted, и может ли это вызвать это исключение.

Если код не помогает, вы можете проверить, есть ли у вас проблема без второго цикла (Вставка). И как выглядит GetToDelete точно? А как выглядят ваши Model и Entity классы и их отношения? И является ли model.Entity действительно другой коллекцией, чем model.Entities (или это опечатка)?

...