初始化入口
在AbpKernelModule類中,通過UnitOfWorkRegistrar.Initialize(IocManager) 方法去初始化


1 /// <summary> 2 /// This class is used to register interceptor for needed classes for Unit Of Work mechanism. 3 /// </summary> 4 internal static class UnitOfWorkRegistrar 5 { 6 /// <summary> 7 /// Initializes the registerer. 8 /// </summary> 9 /// <param name="iocManager">IOC manager</param> 10 public static void Initialize(IIocManager iocManager) 11 { 12 iocManager.IocContainer.Kernel.ComponentRegistered += ComponentRegistered; 13 } 14 15 private static void ComponentRegistered(string key, IHandler handler) 16 { 17 if (UnitOfWorkHelper.IsConventionalUowClass(handler.ComponentModel.Implementation)) 18 { 19 //Intercept all methods of all repositories. 20 handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(UnitOfWorkInterceptor))); 21 } 22 else if (handler.ComponentModel.Implementation.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any(UnitOfWorkHelper.HasUnitOfWorkAttribute)) 23 { 24 //Intercept all methods of classes those have at least one method that has UnitOfWork attribute. 25 //TODO: Intecept only UnitOfWork methods, not other methods! 26 handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(UnitOfWorkInterceptor))); 27 } 28 } 29 }
?
UnitOfWorkInterceptor 攔截器
基于Castle.Core的AOP動態攔截
?
區分同步異步,通過UowManager開啟事務


1 private void PerformUow(IInvocation invocation, UnitOfWorkOptions options) 2 { 3 if (AsyncHelper.IsAsyncMethod(invocation.Method)) 4 { 5 PerformAsyncUow(invocation, options); 6 } 7 else 8 { 9 PerformSyncUow(invocation, options); 10 } 11 } 12 13 private void PerformSyncUow(IInvocation invocation, UnitOfWorkOptions options) 14 { 15 using (var uow = _unitOfWorkManager.Begin(options)) 16 { 17 invocation.Proceed(); 18 uow.Complete(); 19 } 20 }
invocation.Proceed();會嵌套執行,將Uow嵌套包含,嵌套的Uow不會單獨再開啟事務,通過InnerUnitOfWorkCompleteHandle標識,全部完成后complete,提交事務(UnitOfWorkDefaultOptions默認開啟事務)
?
UnitOfWorkManager
UnitOfWorkManager 繼承IUnitOfWorkManager


1 /// <summary> 2 /// Unit of work manager. 3 /// Used to begin and control a unit of work. 4 /// </summary> 5 public interface IUnitOfWorkManager 6 { 7 /// <summary> 8 /// Gets currently active unit of work (or null if not exists). 9 /// </summary> 10 IActiveUnitOfWork Current { get; } 11 12 /// <summary> 13 /// Begins a new unit of work. 14 /// </summary> 15 /// <returns>A handle to be able to complete the unit of work</returns> 16 IUnitOfWorkCompleteHandle Begin(); 17 18 /// <summary> 19 /// Begins a new unit of work. 20 /// </summary> 21 /// <returns>A handle to be able to complete the unit of work</returns> 22 IUnitOfWorkCompleteHandle Begin(TransactionScopeOption scope); 23 24 /// <summary> 25 /// Begins a new unit of work. 26 /// </summary> 27 /// <returns>A handle to be able to complete the unit of work</returns> 28 IUnitOfWorkCompleteHandle Begin(UnitOfWorkOptions options); 29 }
?
在Begin方法中根據option的設置,創建了一個新的Uow,并設置了Uow相應的Completed,Failed,Disposed的方法。
?
?CallContextCurrentUnitOfWorkProvider?
這里有必要提一下CallContextCurrentUnitOfWorkProvider 的對象,他繼承ICurrentUnitOfWorkProvider
CallContextCurrentUnitOfWorkProvider的主要功能其實只有一個:通過current返回當前UOW環境下的UOW實例。
一般思路是:將IUnitOfWork對象定義為實例變量或者是類變量。?但是兩者事實上都不可行。
如果定義為類變量,那就會面臨線程安全的問題,解決方式無非加鎖,但會導致并發能力下降,ABP是web框架,因為鎖導致并發能力下降是不能接受的。
如果定義為實例變量,在同一線程其他地方resolve?CallContextCurrentUnitOfWorkProvider這個實例的時候都會得到一個新的實例,新的實例下current自然是NULL.
ABP的做法是:線程邏輯上下文+線程安全的Dictinoray容器。
線程邏輯上下文用于存儲UOW實例的key,?而線程邏輯上下文對于本線程是全局可訪問的,而同時具有天然的隔離性。這就確保了當前線程的各個地方都可以得到current的UOW的key
線程安全的Dictinoray容器是一個類實例,用于存放UOW的實例,通過UOW的key就可以取到UOW的實例。(引用:?http://www.cnblogs.com/1zhk/p/5309043.html)
這里有兩篇CallContext的博文,推薦看一下
如何實現對上下文(Context)數據的統一管理 [提供源代碼下載]
CallContext和多線程
?
UnitOfWork
1.UnitOfWorkBase
接下來,分析下UnitOfWork是如何封裝事務的。
基于接口隔離原則的考量,ABP作者將UnitOfWork的方法分到了三個不同的接口中,如下圖。
IUnitOfWorkCompleteHandle:定義了UOW同步和異步的complete方法。實現UOW完成時候的邏輯。?
IActiveUnitOfWork:一個UOW除了以上兩個接口中定義的方法和屬性外,其他的屬性和方法都在這個接口定義的。比如Completed,Disposed,Failed事件代理,Filter的enable和disable,以及同步、異步的SaveChanges方法。?
IUnitOfWork:繼承了上面兩個接口。定義了外層的IUnitOfWork的引用和UOW的begin方法。 ABP是通過構建一個UnitOfWork的鏈,將不同的方法納入到一個事務中。
UnitOfWorkBase:這個抽象類實現了上面三個接口中定義的方法,而真正實現事務控制的方法是由這個抽象類的子類實現的(比如,真正創建TransactionScope的操作是在EfUnitOfWork,NhUnitOfWork這樣的之類中實現的)。UOW中除了事務控制邏輯以外的邏輯都是由UnitOfWorkBase抽象類實現的。?


1 /// <summary> 2 /// Defines a unit of work. 3 /// This interface is internally used by ABP. 4 /// Use <see cref="IUnitOfWorkManager.Begin()"/> to start a new unit of work. 5 /// </summary> 6 public interface IUnitOfWork : IActiveUnitOfWork, IUnitOfWorkCompleteHandle 7 { 8 /// <summary> 9 /// Unique id of this UOW. 10 /// </summary> 11 string Id { get; } 12 13 /// <summary> 14 /// Reference to the outer UOW if exists. 15 /// </summary> 16 IUnitOfWork Outer { get; set; } 17 18 /// <summary> 19 /// Begins the unit of work with given options. 20 /// </summary> 21 /// <param name="options">Unit of work options</param> 22 void Begin(UnitOfWorkOptions options); 23 }
UnitOfWorkBase中的Begin實現如下:
1 public void Begin(UnitOfWorkOptions options) 2 { 3 if (options == null) 4 { 5 throw new ArgumentNullException("options"); 6 } 7 8 PreventMultipleBegin(); //通過_isBeginCalledBefore 字段bool判斷是否已經begin 9 Options = options; //TODO: Do not set options like that, instead make a copy? 10 11 SetFilters(options.FilterOverrides); //通過設置過濾器達到全局數據過濾的效果,在ef的實現中,通過引用EntityFramework.DynamicFilter實現 12 13 BeginUow(); 14 }
?
2.開始UnitOfWork
CompleteUow和BeginUow 在UowBase中為抽象方法,具體實現在efUow中,稍后分析
/// <summary>/// Should be implemented by derived classes to complete UOW./// </summary>protected abstract void CompleteUow();
?
3.Complete
Complete方法在UnitOfWorkInterceptor攔截中,PerformSyncUow方法內,執行完invocation.Proceed();會調用Complete方法。
1 /// <inheritdoc/> 2 public void Complete() 3 { 4 PreventMultipleComplete(); //通過_isCompleteCalledBefore字段Bool判斷是否已經Complete,保證只執行一次 5 try 6 { 7 CompleteUow(); 8 _succeed = true; 9 OnCompleted(); //調用完成的事件,在UnitOfWorkManager中設置,當前的UnitOfWork為null 10 } 11 catch (Exception ex) 12 { 13 _exception = ex; 14 throw; 15 } 16 }
?
4.Dispose
1 /// <inheritdoc/> 2 public void Dispose() 3 { 4 if (IsDisposed) 5 { 6 return; 7 } 8 9 IsDisposed = true; 10 11 if (!_succeed) //在Complete是會設置_succeed,沒有成功則執行Faild事件,會將當前的UnitOfWord設為null 12 { 13 OnFailed(_exception); 14 } 15 16 DisposeUow(); //為抽象方法,在子類中實現 17 OnDisposed(); //OnFailed和OnDisposed均在UnitOfWordManage中設置 18 }
?
EfUnitOfWork
1.BeginUow
1 protected override void BeginUow() 2 { 3 if (Options.IsTransactional == true) 4 { 5 var transactionOptions = new TransactionOptions 6 { 7 IsolationLevel = Options.IsolationLevel.GetValueOrDefault(IsolationLevel.ReadUncommitted), 8 }; 9 10 if (Options.Timeout.HasValue) 11 { 12 transactionOptions.Timeout = Options.Timeout.Value; 13 } 14 15 CurrentTransaction = new TransactionScope( //開啟事務,并給定默認為Required 16 Options.Scope.GetValueOrDefault(TransactionScopeOption.Required), 17 transactionOptions, 18 Options.AsyncFlowOption.GetValueOrDefault(TransactionScopeAsyncFlowOption.Enabled) 19 ); 20 } 21 }
?2.CompleteUow
1 protected override void CompleteUow() 2 { 3 SaveChanges(); //遍歷EfContent,調用SaveChange方法 4 if (CurrentTransaction != null) //如果存在事務則執行 5 { 6 CurrentTransaction.Complete(); 7 } 8 }
?