DDD, как сохранить удаления на дочерних объектах с помощью NHibernate? - PullRequest
0 голосов
/ 22 ноября 2018

Имея AggregateRoot и список дочерних сущностей, как вы сохраняете обновленный список потомков после удаления или обновления одного из них?

Это служба уровня приложения

  async Task HandleAsync(RemoveChildRequest request)
        {
            Aggregate aggregate = await _aggregateRepository.GetByIdAsync(request.AggregateId);

            aggregate.RemoveChild(request.ChildId);

            await _aggregateRepository.Update(aggregate);

            await _unitOfWork.CommitAsync();
        }

Это агрегированный метод удаления дочернего элемента.

    public virtual void RemoveChild(Guid ChildId)
    {
        Child kid = _children.Single(item => item.Id == ChildId);

        _children.Remove(kid);
    }

И это репозиторий. Агрегат, как и должно быть, имеет те же данные, но без дочернего элемента он был удален из коллекции.

Update(Aggregate aggregate)
{
      await Session.UpdateAsync(aggregate, aggregate.Id);
}

Это моя конфигурация NHibernate

  mapping
      .HasMany<Children>(Reveal.Member<Aggregate>("Children"))
      .Not.Inverse()
      .Not.KeyNullable()
      .Not.KeyUpdate()
      .Cascade.Delete();

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

Структура

Aggregate 
{
   private virtual IList<Child> _children;
   protected virtual List<Child> Children { get => _children; }
}

Child 
{

}

Таким образом, только родитель имеет ссылку на Child

Я мог бы сделать что-то подобное в Совокупном репозитории

RemoveChild(Child kid) 
{
     Session.DeleteAsync(kid);
}

Но, насколько мне известно, репозитории должны быть только для конкретных агрегатов.

Меня интересует, как будет выглядеть код, который будет действительно сохранять изменения в хранилище данных?Как вы удалите ребенка.Репозиторий.

Ответы [ 3 ]

0 голосов
/ 26 ноября 2018

нашел мой ответ здесь

отображение nhibernate: на коллекцию с cascade = "all-delete-orphan" больше не ссылались

и здесь

свойство Стратегии доступа в nhibernate

Конфигурация NHibernate

    mapping
        .HasMany<Child>(Reveal.Member<Order>("Children"))
        .Access.LowerCaseField(Prefix.Underscore)
        .Cascade.AllDeleteOrphan()
        .Not.KeyNullable()
        .Not.KeyUpdate();
0 голосов
/ 29 ноября 2018

Вот как это делается с отображением ByCode, важно colmap.Cascade (Cascade.All).Надеюсь, это поможет.

public class Client
{
    public virtual int ClientId { get; protected set; }
    public virtual string ClientName { get; protected set; }
    public virtual IList<ClientLocation> ClientLocations { get; protected set; }

    protected Client()
    {
        this.ClientLocations = new List<ClientLocation>();
    }
}

public class ClientLocation
{
    public virtual int ClientLocationId { get; protected set; }
    public virtual Client Client { get; protected set; }
    public virtual string LocationName { get; protected set; }

    protected ClientBranch()
    {
    }
}

Отображения

public class ClientMap : ClassMapping<Client>
{        
    public ClientMap() {
    Lazy(true);

        Id(x => x.ClientId, map => map.Generator(Generators.Identity));
    Property(x => x.ClientName);

        Bag(x => x.ClientLocations, colmap => { colmap.Key(x => x.Column("CLIENTID")); colmap.Cascade(Cascade.All); }, map => { map.OneToMany(); });
    }
}


public class ClientLocationMap : ClassMapping<ClientLocation>
{
    public ClientLocationMap()
    {
    Lazy(true);

        Id(x => x.ClientLocationId, map => map.Generator(Generators.Identity));
    Property(x => x.LocationName);

        ManyToOne(x => x.Client, map => { map.Column("CLIENTID"); map.NotNullable(true); map.Cascade(Cascade.All); });
    }
}
0 голосов
/ 23 ноября 2018

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

Следовательно, вы правы - Repository выберет только родителя.Затем у вас будет команда RemoveChild, которая будет действовать на этот экземпляр и опубликует событие ChildRemoved, которое уберет ребенка из списка.

...