DDD之EFCore发布领域事件的时机

# DDD之EFCore发布领域事件的时机

(1)在聚合根的实体对象的ChangeName()、构造方法等方法中立即发布领域事件,因为无论是应用服务还是领域服务,最终要调用聚合根中的方法来操作聚合,我们这样做可以确保领域事件不会被漏掉。

缺点:

  • 存在重复发送领域事件的情况
  • 领域事件发布的太早:在实体类的构造方法中发布领域事件,但是有可能因为数据验证没通过等原因,我们最终没有把这个新增的实体保存到数据库中,我们这样在构造方法中过早地发布领域事件就会导致“误报”

(2)把领域事件的发布延迟到上下文保存修改时。实体中只是注册要发布的领域事件,然后在上下文 的SaveChanges方法被调用时,我们再发布事件。

  • 供聚合根进行事件注册的接口IDomainEvents,所有聚合根实体继承BaseEntity.cs

image-20220319174449596

  • 重写SaveChangesAsync
public override int SaveChanges(bool acceptAllChangesOnSuccess)
    {
        throw new NotImplementedException("Don not call SaveChanges, please call SaveChangesAsync instead.");
    }

    public async override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
    {
        var domainEntities = this.ChangeTracker.Entries<IDomainEvents>()
                        .Where(x => x.Entity.GetDomainEvents().Any());
        var domainEvents = domainEntities
            .SelectMany(x => x.Entity.GetDomainEvents()).ToList();
        domainEntities.ToList()
            .ForEach(entity => entity.Entity.ClearDomainEvents());
        foreach (var domainEvent in domainEvents)
        {
            await mediator.Publish(domainEvent);
        }
        return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
    }

image-20220319174657398

  • 实体类改变的时候注册事件,SaveChangesAsync时会发布事件

image-20220319174826958

  • 执行添加接口的时候,事件注册后保存前发布,SaveChangesAsync会回滚失败

image-20220319174948374

posted @ 2022-04-08 17:34  peng_boke  阅读(354)  评论(0编辑  收藏  举报