【发布时间】:2018-10-31 09:35:58
【问题描述】:
要禁用与用户关联的个人资料,我们通常
- 从数据库加载用户
- 调用
User.RemoveProfile(ProfileId)方法。 - 在此方法中,我们将在列表中找到指定的配置文件,然后调用
Profile.Disable()方法 - 在
Profile.Disable()中,我们引发ProfileDisabled事件。 - 我们将用户 + 相关实体(在这种情况下为配置文件)完善到 DB。
当前事件存储在每个实体中。当我们将用户持久保存在数据库中时,我们会通过用户而不是所有相关配置文件下的事件。因此,我们不会调度配置文件事件,它们会丢失。
这是我们用来调度事件的代码供您参考:
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 不知道相关实体。这样就没有办法访问相关事件了。
如何处理这种情况?这是否意味着只有聚合根才能引发事件?
谢谢 赛博
【问题讨论】:
-
我不是 C# 专家,但你不能重载
public IReadOnlyList<DomainEvent> Events => _events.AsReadOnly();方法吗?在User类中,它应该返回自己的事件和嵌套配置文件中的事件 -
这个想法通常是所有交互都应该通过 AR 进行,所以也许这就是要走的路。此外,如果您在 AR 中偏爱值对象而不是实体,那么 AR 无论如何都必须处理事件。我会按照这个计划去:)
-
确实如此。很好的解决方案。我们发现的另一种选择是依靠 EF Core 列出所有添加/修改/删除的实体,遍历它们并调度相关事件
标签: .net .net-core event-handling domain-driven-design repository-pattern