本地事件总线

    以下介绍了两种发布本地事件的方法.

    可以 并且使用发布本地事件.

    示例: 产品的存货数量发生变化时发布本地事件

    PublishAsync 方法需要一个参数:事件对象,它负责保持与事件相关的数据,是一个简单的普通类:

    即使你不需要传输任何数据也需要创建一个类(在这种情况下为空类).

    实体不能通过依赖注入注入服务,但是在实体/聚合根类中发布本地事件是非常常见的.

    示例: 在聚合根方法内发布本地事件

    AggregateRoot 类定义了 AddLocalEvent 来添加一个新的本地事件,事件在聚合根对象保存(创建,更新或删除)到数据库时发布.

    IGeneratesDomainEvents 接口

    实际上添加本地事件并不是 AggregateRoot 类独有的. 你可以为任何实体类实现 IGeneratesDomainEvents. 但是 AggregateRoot 默认实现了它简化你的工作.

    它是如何实现的?

    调用 AddLocalEvent 不会立即发布事件. 当你将更改保存到数据库时发布该事件;

    • 对于 EF Core, 它在 DbContext.SaveChanges 中发布.
    • 对于 MongoDB, 它在你调用仓储的 InsertAsync, 或 DeleteAsync 方法时发由 (因为MongoDB没有更改跟踪系统).

    一个服务可以实现 ILocalEventHandler<TEvent> 来处理事件.

    示例: 处理上面定义的StockCountChangedEvent

    这就是全部,MyHandler 由ABP框架自动发现,并在发生 StockCountChangedEvent 事件时调用 HandleEventAsync.

    • 事件可以由0个或多个处理程序订阅.
    • 一个事件处理程序可以订阅多个事件,但是需要为每个事件实现 ILocalEventHandler<TEvent> 接口.

    如果您执行数据库操作并在事件处理程序中使用,那么您可能需要创建一个工作单元,因为一些存储库方法需要在活动的工作单元中工作. 确保处理方法设置为 virtual,并为该方法添加一个 [UnitOfWork] attribute. 或者手动使用 IUnitOfWorkManager 创建一个工作单元范围.

    • 如果处理程序抛出一个异常,它会影响发布该事件的代码. 这意味着它在 调用上获得异常. 因此如果你想隐藏错误,在事件处理程序中使用try-catch. *如果在一个范围内执行的事件发布的代码,该事件处理程序也由工作单元覆盖. 这意味着,如果你的UOW是事务和处理程序抛出一个异常,事务会回滚.

    发布实体创建,更新,删除事件是常见的操作. ABP框架为所有的实体自动发布这些事件. 你只需要订阅相关的事件.

    示例: 订阅用户创建事件

    这个类订阅 EntityCreatedEventData<IdentityUser>,它在用户创建后发布. 你可能需要向新用户发送一封”欢迎”电子邮件.

    这些事件有两种类型:过去时态的事件和进行时态的事件.

    当相关工作单元完成且实体更改成功保存到数据库时,将发布带有过去时态的事件. 如果在这些事件处理程序上抛出异常,则无法回滚事务,因为事务已经提交.

    事件类型;

    • EntityCreatedEventData<T> 当实体创建成功后发布.
    • EntityDeletedEventData<T> 当实体删除成功后发布.
    • EntityChangedEventData<T> 当实体创建,更新,删除后发布. 如果你需要监听任何类型的更改,它是一种快捷方式 - 而不是订阅单个事件.

    带有进行时态的事件在完成事务之前发布(如果数据库事务由所使用的数据库提供程序支持). 如果在这些事件处理程序上抛出异常,它会回滚事务,因为事务还没有完成,更改也没有保存到数据库中.

    事件类型;

    • EntityCreatingEventData<T> 当新实体保存到数据库前发布.
    • EntityUpdatingEventData<T> 当已存在实体更新到数据库前发布.
    • EntityDeletingEventData<T> 删除实体前发布.
    • EntityChangingEventData<T> 当实体创建,更新,删除前发布. 如果你需要监听任何类型的更改,它是一种快捷方式 - 而不是订阅单个事件.

    它是如何实现的?

    • 对于 EF Core, 他们在 DbContext.SaveChanges 发布.
    • 对于 MongoDB, 在你调用仓储的 InsertAsync, 或 DeleteAsync 方法发布(因为MongoDB没有更改追踪系统).