DDD,如何使用NHibernate持久删除子实体?

时间:2018-11-22 15:01:24

标签: nhibernate architecture software-design

拥有一个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();

提交完成后,将不会对数据库进行任何更新。我觉得这很正常,因为我只从children集合中删除了一个条目,仅此而已。

结构

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

Child 
{

}

因此只有父母拥有对孩子的引用

我可以在汇总存储库中执行类似的操作

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

但是据我所知,存储库应仅是特定于聚合的。

我对将更改持久保存到数据存储中的代码的外观感兴趣吗?您如何移除孩子。存储库。

3 个答案:

答案 0 :(得分:1)

在这里找到我的答案

nhibernate mapping: A collection with cascade="all-delete-orphan" was no longer referenced

在这里

property Access strategies in nhibernate

NHibernate配置

    mapping
        .HasMany<Child>(Reveal.Member<Order>("Children"))
        .Access.LowerCaseField(Prefix.Underscore)
        .Cascade.AllDeleteOrphan()
        .Not.KeyNullable()
        .Not.KeyUpdate();

答案 1 :(得分:-1)

这是通过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); });
    }
}

答案 2 :(得分:-2)

如果子元素属于(即组成而不是关联),则必须通过AggregateRoot而不是独立地进行子实体的删除或添加。而且,子级应该是 Value Objects ,而不是自身的合计。

因此,您是对的-Repository仅会获取父级。然后,您将拥有RemoveChild命令,该命令将对该实例起作用,并发布一个ChildRemoved事件,该事件会将孩子带离列表。