private static IUnitOfWork GetCurrentUow(ILogger logger) { unitOfWorkKey = CallContext.LogicalGetData(ContextKey) as string; if (unitOfWorkKey == null) { return null; } IUnitOfWork unitOfWork; if (!UnitOfWorkDictionary.TryGetValue(unitOfWorkKey, out unitOfWork)) {//如果根据key获取不到当前工作单元,那么就从当前线程集合(CallContext)中释放key CallContext.FreeNamedDataSlot(ContextKey); return null; } if (unitOfWork.IsDisposed) {//如果当前工作单元已经dispose,那么就从工作单元集合中移除,并将key从当前线程集合(CallContext)中释放 logger.Warn(); UnitOfWorkDictionary.TryRemove(unitOfWorkKey, out unitOfWork); CallContext.FreeNamedDataSlot(ContextKey); return null; } return unitOfWork; }
总的说来,所有的工作单元存储在线程安全的字典对象中(ConcurrentDictionary),每个主线程共用一个工作单元的实现,通过线程集合(CallContext)实现。
UnitOfWork实现
从上面的分析可以看出,ABP/Domain/Uow路径下,主要只是提供了一套抽象接口,并没有提供实际的实现,IUnitOfWork最多也只是提供了一个UnitOfWorkBase抽象类,这样的自由性非常大,我非常喜欢这种方式。
当然ABP也另起了几个项目来提供一些常用的ORM的Unit of Work封装:
1.Ef: Abp.EntityFramework/EntityFramework/Uow
2.NH: Abp.NHibernate/NHibernate/Uow
3.Mongo: Abp.MongoDB/MongoDb/Uow
4.Memory: Abp.MemoryDb/MemoryDb/Uow
其中Mongo和Memory都没有进行实质性的单元操作,Ef中使用TransactionScope进行单元操作,NH中使用ITransaction来进行单元操作。
ABP/Domain/Uow结构说明
UnitOfWorkRegistrar····································注册拦截器,实现两种默认的UnitOfWork,详见最上面的默认行为
UnitOfWorkInterceptor··································Unit of Work拦截器,实现以AOP的方式进行注入单元控制
IUnitOfWorkManager····································简洁的UnitOfWork管理对象
UnitOfWorkManager··································IUnitOfWorkManager默认实现
ICurrentUnitOfWorkProvider···························当前UnitOfWork管理对象
CallContextCurrentUnitOfWorkProvider············ICurrentUnitOfWorkProvider默认实现
IUnitOfWork···············································工作单元对象(Begin、SaveChanges、Complete、Dispose)