Сначала код EF: как удалить строку из коллекции сущности, следуя DDD? - PullRequest
17 голосов
/ 02 декабря 2011

Итак, вот сценарий:

DDD заявляет, что вы используете хранилище для получения совокупного корня, а затем используете его для добавления / удаления в любые имеющиеся у него коллекции.

Добавление просто,Вы просто звоните .Add(Item item) на Collection, к которому хотите добавить.Новая строка добавляется в базу данных при сохранении.Однако удаление происходит по-другому - вызов .Remove(Item item) не удаляет элемент из базы данных, он просто удаляет внешний ключ.Так что, хотя, да, технически он больше не является частью коллекции, он все еще находится в базе данных.

Чтение, единственное решение - удалить его, используя контекст данных.Но в соответствии с DDD объект домена не должен знать о контексте данных, поэтому удаление должно быть выполнено за пределами домена.

Как правильно это сделать?Или приемлемо оставить базу данных, заполненную сиротами (возможно, запустив процедуру для их очистки)?

Ответы [ 4 ]

11 голосов
/ 02 декабря 2011

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

Хотя доменным объектам не разрешено знать о контексте объекта, IDomainEventHandler есть - поэтому я получилDomainObjectDeletionHandler, который удаляет «удаленные» объекты из контекста объекта, прежде чем элемент управления вернется на уровень приложения и изменения будут сохранены.

Для получения дополнительной информации я написал блог омоя реализация событий домена и то, как я подошел, подключив все вместе.

Надеюсь, это поможет:)

Edit

Например, если у вас естьOrder класс с коллекцией OrderItems типа OrderItem:

public class Order
{
    // Other stuff

    public void RemoveOrderItem(int orderItemId)
    {
        var orderItemToRemove = OrderItems.First(oi => oi.Id == orderItemId)

        OrderItems.Remove(orderItemToRemove);

        DomainEvents.Raise(new OrderItemRemoved(orderItemToRemove));
    }
}
5 голосов
/ 12 июня 2013

При удалении дочерней сущности из коллекции EF оставляет ее как потерянную, удаляя только внешний ключ.

Если вы не хотите явно удалять ее с помощью DbContext, вы можете использовать то, что онаназывается «Идентификационные отношения» (http://msdn.microsoft.com/en-us/library/ee373856.aspx внизу).

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

Как только вы это сделаете, при удалении сущности из коллекции родителя она будет удалена изстол тоже.

3 голосов
/ 02 декабря 2011

Я не знаю, является ли это разработанным, но если у объекта детализации есть составной ключ, содержащий ключевые столбцы его главного объекта, он будет автоматически удален, если вы удалите его из коллекции главного объекта. Если у вас есть объект Order с ключом OrderID и навигационным свойством ICollection OrderLines, присвойте OrderLine составной ключ, содержащий OrderID и OrderLineID.

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

0 голосов
/ 03 июля 2013

Почему бы не использовать два репозитория?

var parent = ParentRepo.Get(parentId);
parent.Children.Remove(childId); // remove it from the property Collection
ChildRepo.Delete(childId); // delete it from the database
ParentRepo.Commit(); // calls underlying context.SaveChanges()

Предполагая, что вы делитесь контекстами через IOC / DI, вызов commit с одним репо будет фиксировать оба, в противном случае просто вызовите также ChildRepo.Commit.

...