Entity Framework - Очистить дочернюю коллекцию - PullRequest
26 голосов
/ 13 января 2010

Я столкнулся с интересной проблемой, связанной с Entity Framework, и, основываясь на коде, который мне пришлось использовать для ее решения, я подозреваю, что мое решение далеко не идеально. У меня есть отношение 1-ко-многим между таблицей A и таблицей B, где объекты в таблице B имеют ссылку на таблицу A. У меня есть сценарий, в котором я хочу одновременно удалить всех дочерних элементов в таблице A, и я подумал, что этого можно добиться, просто очистив коллекцию:

Entity.Children.Clear()

К сожалению, когда я попытался сохранить изменения, это вызвало нарушение внешнего ключа.

Отношения добавляются или удалено из набора ассоциаций 'FK_EntityB_EntityA. С кардинальностью ограничения, соответствующие «EntityB» также должен быть добавлен или удален.

Решение, которое я придумал, состояло в том, чтобы вручную удалить объект через DeleteObject () контекста сущности, но я просто знаю, что используемая логика ошибочна.

while (collection.Any())
    Entities.DeleteObject(collection.First());

С одной стороны, тот факт, что мне пришлось использовать цикл Where (), кажется далеко не идеальным, но я полагаю, что это чисто семантическая оценка с моей стороны. В любом случае, что-то не так с тем, как я это делаю, или, возможно, есть лучший способ очистить коллекцию дочерних сущностей от сущностей, чтобы Entity Framework правильно вызывала удаление хранилища данных на всех удаленных объектах?

Ответы [ 3 ]

21 голосов
/ 13 января 2010

Clear() удаляет ссылку на объект, а не на сам объект.

Если вы хотите, чтобы всегда было одной и той же операцией, вы можете обработать AssociationChanged:

Entity.Children.AssociationChanged += 
    new CollectionChangeEventHandler(EntityChildrenChanged);
Entity.Children.Clear();            

    private void EntityChildrenChanged(object sender,
        CollectionChangeEventArgs e)
    {
        // Check for a related reference being removed. 
        if (e.Action == CollectionChangeAction.Remove)
        {
            Context.DeleteObject(e.Element);
        }
    }

Вы можете встроить это в свою сущность, используя частичный класс.

6 голосов
/ 12 сентября 2012

Вы можете создать Идентификационные отношения между родительскими и дочерними объектами, и EF удалит дочерний объект, когда вы удалите его из родительской коллекции.

    public class Parent
    {
      public int ParentId {get;set;}
      public ICollection<Child> Children {get;set;}
    }

    public class Child
    {          
      public int ChildId {get;set;}
      public int ParentId {get;set;}
    }

Конфигурация отображения:

    modelBuilder.Entity<Child>().HasKey(x => new { x.ChildId, x.ParentId });
    modelBuilder.Entity<Parent>().HasMany(x => x.Children).WithRequired().HasForeignKey(x => x.ParentId);
5 голосов
/ 09 июля 2014

Трюк: при настройке отношений между Родителем и Дочерним, вы должны создать «составной» ключ для дочернего элемента. Таким образом, когда вы говорите Родителю удалить 1 или все его дочерние элементы, связанные записи будут фактически удалены из базы данных.

Чтобы настроить составной ключ с помощью Fluent API:

modelBuilder.Entity<Child>().HasKey(t => new { t.ParentId, t.ChildId });

Затем, чтобы удалить связанных детей:

var parent = _context.Parents.SingleOrDefault(p => p.ParentId == parentId);

var childToRemove = parent.Children.First(); // Change the logic 
parent.Children.Remove(childToRemove);

// you can delete all children if you want 
// parent.Children.Clear();

_context.SaveChanges();

Готово!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...