相关实体的DDD调度事件

时间:2018-10-31 09:35:58

标签: .net .net-core event-handling domain-driven-design repository-pattern

通常,要禁用与用户关联的个人资料

  • 从数据库加载用户
  • 调用User.RemoveProfile(ProfileId)方法。
  • 在此方法中,我们将在列表中找到指定的配置文件,然后调用Profile.Disable()方法
  • Profile.Disable()内,我们引发了ProfileDisabled事件。
  • 我们完善了与数据库相关的用户+相关实体(在这种情况下为个人资料)。

当前,事件存储在每个实体中。当我们将用户持久存储在数据库中时,我们将在用户下而不是在所有关联的配置文件下进行事件。因此,我们不会调度配置文件事件,它们会丢失。

供您参考,这是我们用于调度事件的代码:

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();
}

您可以看到Entity不了解相关实体。无法访问相关事件。

如何处理这种情况?这是否意味着只有汇总根可以引发事件?

Thx 塞巴

1 个答案:

答案 0 :(得分:0)

我想您有两个实体的集合:用户和个人资料。而用户就是AR。

对聚合执行操作时会引发事件,因此应将其存储在AR中。

在您的情况下,操作为“ user.removeProfile(profileId)”,因此AR应引发事件“ ProfileRemovedFromUser”或类似事件。

注意:您的UL含糊不清,因为您对同一件事使用“移除”和“禁用”一词。您应该只使用一个词。