[Abp vNext 源码分析] - 4. 工作单元 (4)

这里可以看到,ABP vNext 完全剥离了具体事务或者回滚的实现方法,都是移动到具体的模块进行实现的,也就是说在调用了 Complete() 方法之后,我们的事务就会被提交了。

本小节从创建、提交、释放这三个生命周期讲解了工作单元的原理和实现,关于具体的事务和回滚实现,我会放在下一篇文章进行说明,这里就不再赘述了。

为什么工作单元常常配合 using 语句块 使用,就是因为在提交工作单元之后,就可以自动调用 Dispose() 方法,对工作单元的状态进行校验,而不需要我们手动处理。

using(var uowA = _uowMgr.Begion()) { uowA.Complete(); } 2.3.3 保留工作单元

在 ABP vNext 里面,工作单元有了一个新的动作/属性,叫做 是否保留(Is Reserved)。它的实现也比较简单,指定了一个 ReservationName,然后设置 IsReserved 为 true 就完成了整个动作。

那么它的作用是什么呢?这块内容我会在工作单元管理器小节进行解释。

2.4 工作单元管理器

工作单元管理器在工作单元的原理/实现里面已经有过了解,工作单元管理器主要负责工作单元的创建。

这里我再挑选一个工作单元模块的单元测试,来说明什么叫做 保留工作单元

[Fact] public async Task UnitOfWorkManager_Reservation_Test() { _unitOfWorkManager.Current.ShouldBeNull(); using (var uow1 = _unitOfWorkManager.Reserve("Reservation1")) { _unitOfWorkManager.Current.ShouldBeNull(); using (var uow2 = _unitOfWorkManager.Begin()) { // 此时 Current 值是 Uow2 的值。 _unitOfWorkManager.Current.ShouldNotBeNull(); _unitOfWorkManager.Current.Id.ShouldNotBe(uow1.Id); await uow2.CompleteAsync(); } // 这个时候,因为 uow1 是保留工作单元,所以不会被获取到,应该为 null。 _unitOfWorkManager.Current.ShouldBeNull(); // 调用了该方法,设置 uow1 的 IsReserved 属性为 false。 _unitOfWorkManager.BeginReserved("Reservation1"); // 获得到了值,并且诶它的 Id 是 uow1 的值。 _unitOfWorkManager.Current.ShouldNotBeNull(); _unitOfWorkManager.Current.Id.ShouldBe(uow1.Id); await uow1.CompleteAsync(); } _unitOfWorkManager.Current.ShouldBeNull(); }

通过对代码的注释和断点调试的结果,我们知道了通过 Reserved 创建的工作单元它的 IsReserved 属性是 true,所以我们调用 IUnitOfWorkManager.Current 访问的时候,会忽略掉保留工作单元,所以得到的值就是 null。

但是通过调用 BeginReserved(string name) 方法,我们就可以将指定的工作单元置为 当前工作单元,这是因为调用了该方法之后,会重新调用工作单元的 Initialize() 方法,在该方法内部,又会将 IsReserved 设置为 false 。

public virtual void Initialize(UnitOfWorkOptions options) { // ... 其他代码。 // 注意这里。 IsReserved = false; }

保留工作单元的用途主要是在某些特殊场合,在某些特定条件下不想暴露给 IUnitOfWorkManager.Current 时使用。

2.5 工作单元拦截器

如果我们每个地方都通过工作单元管理器来手动创建工作单元,那还是比较麻烦的。ABP vNext 通过拦截器,来为特定的类型(符合规则)自动创建工作单元。

关于拦截器的注册已经在文章最开始说明了,这里就不再赘述,我们直接来看拦截器的内部实现。其实在拦截器的内部,一样是使用工作单元拦截器我来为我们创建工作单元的。只不过通过拦截器的方式,就能够无感知/无侵入地为我们构造健壮的数据持久化机制。

public override void Intercept(IAbpMethodInvocation invocation) { // 如果类型没有标注 UnitOfWork 特性,或者没有继承 IUnitOfWorkEnabled 接口,则不创建工作单元。 if (!UnitOfWorkHelper.IsUnitOfWorkMethod(invocation.Method, out var unitOfWorkAttribute)) { invocation.Proceed(); return; } // 通过工作单元管理器构造工作单元。 using (var uow = _unitOfWorkManager.Begin(CreateOptions(invocation, unitOfWorkAttribute))) { invocation.Proceed(); uow.Complete(); } }

关于在 ASP.NET Core MVC 的工作单元过滤器,在实现上与拦截器大同小异,后续讲解 ASP.NET Core Mvc 时再着重说明。

三、总结

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdfdx.html