代码之家  ›  专栏  ›  技术社区  ›  Seb

相关实体DDD调度事件

  •  1
  • Seb  · 技术社区  · 7 年前

    • 从数据库加载用户
    • 打电话给 User.RemoveProfile(ProfileId) 方法。
    • 在这个方法中,我们将在一个列表中找到指定的概要文件,然后调用 Profile.Disable()
    • 在 Profile.Disable() 我们提高价格 ProfileDisabled
    • 我们将用户+相关实体(在这种情况下是profiles)完善到DB。

    当前事件存储在每个实体中。当我们在数据库中持久化用户时,我们会在user下处理事件,而不是在所有相关的概要文件下。因此,我们不发送概要文件事件,它们就会丢失。

    public abstract class Repository
    {
        private readonly IMediator _mediator;
    
        protected Repository(IMediator mediator) => _mediator = mediator;
    
        // Future: Use EventStore for audit
        /* Bug: Disable profile raises an event stored at the profile level. When user gets updated only
           user events are dispatched. Profile events are lost... */
        protected async Task DispatchEventsAsync(Entity entity, CancellationToken token)
        {
            Ensure.Any.IsNotNull(entity, nameof(entity));
            await Task.WhenAll(entity.Events.Select(e => _mediator.Publish(e, token)));
            entity.SuppressEvents();
        }
    }
    

    Entity 是:

    public interface IEntity { }
    
    public abstract class Entity : IEntity
    {
        private readonly List<DomainEvent> _events = new List<DomainEvent>();
    
        [NotMapped]
        public IReadOnlyList<DomainEvent> Events => _events.AsReadOnly();
        public bool HasEvents => _events.Any();
    
        protected void Emit(DomainEvent eventItem)
        {
            if (eventItem != null && !_events.Contains(eventItem))
                _events.Add(eventItem);
        }
    
        public void SuppressEvents() => _events.Clear();
    }
    

    如您所见,实体并不知道相关的实体。这意味着无法访问相关事件。

    你怎么处理这个案子?这是否意味着只有聚合根才能引发事件?

    谢谢 Seb公司

    1 回复  |  直到 7 年前
        1
  •  0
  •   choquero70    7 年前

    我猜您有一个包含两个实体的聚合:User和Profile。用户是AR。

    在对聚合执行操作时会引发事件,因此应将它们与AR一起存储。

    在您的例子中,操作是“user.removeProfile(profileId)”,因此AR应该引发事件“ProfileRemovedFromUser”或类似的事件。

    注意:你的UL是模棱两可的,因为你用词删除和禁用为同一件事。你应该只用一个词。

    推荐文章