Подтвердить что ты не робот

Entity Framework - очистка детской коллекции

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

Entity.Children.Clear()

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

Добавляется отношение или удалено из набора AssociationSet 'FK_EntityB_EntityA. С мощностью ограничений, соответствующий "EntityB" также должны быть добавлены или удалены.

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

Вы можете создать идентификацию отношений между родительскими и дочерними объектами, а 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);

Ответ 3

Трюк: при настройке отношений между родителем и ребенком вы должны создать "составной" ключ для ребенка. Таким образом, когда вы сообщите родительу удалить 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();

Готово!