ABP框架 UnitOfWorkAttribute
记录下:
使用Castle.DynamicProxy实现动态代理
参考项目地址:https://github.com/f135ta/SimpleProxy
要点:
方法上的 Attribute 与 对应的拦截器一一对应
具体的Proxy由Castle.DynamicProxy实现
创建UnitOfWork
1.由IUnitOfWorkManager在内部创建
2. 创建 IUnitOfWork
这里使用到了 _currentUnitOfWorkProvider 类来获取已存在的 IUnitOfWork。
注意 “AsyncLocal” 用法 多线程共享变量,
在异步情况下(async await) 等待之前的线程 与 等待之后的线程可能不是同一个线程。
这个 ICurrentUnitOfWorkProvider 很关键
设置Unitofwork值的,也将IUnitofwork变量内部 Outer 设置了。
当该工作单元完成后, ICurrentUnitOfWorkProvider.Current 的值就设置成了null,为下一个工作单元做准备。
仓储中的DbContext从何而来
如图:
再看下 IDbContextProvider 内部,这里以EF 为例。
值是从当前的工作单元中创建,由
ICurrentUnitOfWorkProvider 将 工作单元 与 仓储 连接 。
换句话说,工作单元 与 仓储操 操作的DbContext 是同一个。
外部工作单元从何而来IUnitOfWork.Outer
看图,这是个类,类中有几个方法。
由ioc容器创建该类,顺便注入了仓储与 工作单元管理器。
在BeforeRun方法中手动创建了一个工作单元,using语句块中执行 _userRepository.Insert 方法时,会在 UnitOfWorkInterceptor 拦截器中执行(如下图) 创建工作单元
在此时刻,由于手动创建的工作单元没执行 Complete()方法,那么 多线程共享变量(如下图AsyncLocalCurrentUnitOfWorkProvider继承ICurrentUnitOfWorkProvider 对Current的实现)
ICurrentUnitOfWorkProvider.Current 值没设置为null。
那么此时拦截器中创建的工作单元就 等于 手动创建的工作单元。
如图:表示工作单元已存在
本文作者:youliCC