下面就以一个简单的例子来演示实现方式之一,即发件箱模式。
public abstract class IEntity { private int id; public virtual int Id { get { return id; } protected set { id = value; } } private List<IEvent> _domainEvents; public IReadOnlyCollection<IEvent> DomainEvents => _domainEvents?.AsReadOnly(; public void AddDomainEvent(IEvent eventItem { _domainEvents = _domainEvents ?? new List<IEvent>(; _domainEvents.Add(eventItem; } public void RemoveDomainEvent(IEvent eventItem { _domainEvents?.Remove(eventItem; } public void ClearDomainEvents( { _domainEvents?.Clear(; } }
public class CreateOrderEvent:IEvent { public Guid EventId { get; set; } public int CustomerId { get; set; } public CreateOrderEvent(Guid EventId,int customerId { this.EventId = EventId; CustomerId = customerId; } }
我把事件简化到实体类里面,也可以不需要这个IEntity,那每次都需要自己创建order的同时创建一个事件,当然事件集合需要自己定义存起来。
这里的邮件就是事件了,而投递就是事件发布。
我新建一个order,同时把发布的order事件存到数据,这就是发件箱模式。好多数据库和中间件操作的最终一致性大体都是这个模式,借助数据库的分布式事务。
public sealed class OutBoxMessageInterceptor:SaveChangesInterceptor { public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default { DbContext? dbContxt = eventData.Context; if (dbContxt is null { return base.SavingChangesAsync(eventData, result, cancellationToken; } var events = dbContxt.ChangeTracker.Entries<IEntity>(.Select(x => x.Entity.SelectMany(x => { List<IEvent> entiti