Abp Uow 設計

初始化入口

在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     }
UnitOfWorkRegistrar

?

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         }
PerformUow

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     }
IUnitOfWorkManager

?

在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的操作是在EfUnitOfWorkNhUnitOfWork這樣的之類中實現的)。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     }
IUnitOfWork

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         }

?

轉載于:https://www.cnblogs.com/Hai--D/p/5482009.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/457943.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457943.shtml
英文地址,請注明出處:http://en.pswp.cn/news/457943.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python3.8 實現鼠標自動移動_“新生報到”!【移動機器人 HD-1500】負載1500kg,實現了重型貨物運輸的自動化...

2020年第三季度歐姆龍自動化&#xff08;中國&#xff09;有限公司新品【移動機器人 HD-1500】即日起在中國市場首次對外發布&#xff0c;實現了重型貨物運輸的自動化。這款最新的自動化移動機器人重型載荷能力為1500 kg&#xff01;更高的載荷能力可以令客戶實現以前無法實現的…

Linux 關閉服務后 鼠標 鍵盤用不了

大部分情況下我們做實驗都是使用虛擬機&#xff0c;但是個人比較本實在太老了&#xff0c;性能有限&#xff0c;所以虛擬機里面的系統啟動神慢&#xff0c;怎么辦&#xff1f;把系統中自己用不到的服務全部關閉掉唄&#xff0c;如下for i in chkconfig --list | awk {print $1}…

對session的理解

java Servlet API引入session 機制來跟蹤客戶的狀態&#xff0c;session指的是在一段時間內&#xff0c;單個客戶和web服務器之間一連串的交互過程&#xff0c;在一個session中&#xff0c;一個客戶可能會多次請求同一個網頁&#xff0c;也可能請求多個不同服務器資源&#xff…

android 監聽本機網絡請求_fiddler如何抓取https請求實現fiddler手機抓包-證書安裝失敗100%解決...

一、HTTP協議和HTTPS協議。(1) HTTPS協議HTTP協議SSL協議&#xff0c;默認端口&#xff1a;443(2) HTTP協議&#xff08;HyperText Transfer Protocol&#xff09;&#xff1a;超文本傳輸協議。默認端口&#xff1a;80&#xff0c;其中包含請求和響應兩部分&#xff0c;其中請求…

c語言筆試題總結2

下列各題A)、B)、C)、D)四個選項中&#xff0c;只有一個選項是正確的&#xff0c;請將正確選項涂寫在答題卡相應位置上&#xff0c;答在試卷上不得分。(1)算法的時間復雜度是指_______。A)執行算法程序所需要的時間B)算法程序的長度C)算法執行過程中所需要的基本運算次數D)算法…

C#的四舍五入函數

2019獨角獸企業重金招聘Python工程師標準>>> 1.四舍六入&#xff08;國外的四舍五入&#xff09; Math.Round&#xff08;num&#xff09;; 2.四舍五入 Math.Round(num,MidpointRounding.AwayFromZero); 轉載于:https://my.oschina.net/CrazyBoy1024/blog/746268

C語言筆試題總結3

4. static有什么用途&#xff1f;&#xff08;請至少說明兩種&#xff09;1.限制變量的作用域2.設置變量的存儲域7. 引用與指針有什么區別&#xff1f;1) 引用必須被初始化&#xff0c;指針不必。2) 引用初始化以后不能被改變&#xff0c;指針可以改變所指的對象。2) 不存…

【BZOJ2243】 [SDOI2011]染色

Description 給定一棵有n個節點的無根樹和m個操作&#xff0c;操作有2類&#xff1a; 1、將節點a到節點b路徑上所有點都染成顏色c&#xff1b; 2、詢問節點a到節點b路徑上的顏色段數量&#xff08;連續相同顏色被認為是同一段&#xff09;&#xff0c;如“112221”由3段組成&am…

jquery easyui DataGrid 數據表格 屬性

擴展自 $.fn.panel.defaults &#xff0c;用 $.fn.datagrid.defaults 重寫了 defaults 。 依賴 panelresizablelinkbuttonpagination用法 1. <table id"tt"></table> 1. $(#tt).datagrid({ 2. url:datagrid_data.json, 3. columns:[…

C語言筆試題總結

1. 下面這段代碼的輸出是多少(在32位機上). char *p; // 4 char *q[20]; // 80 char *m[20][20]; // 1600 int (*n)[10]; // 4 struct MyStruct { char dda; double dda1; int type ; }&#xff1b; MyStruct k; // 24 printf("%d %d %d %d",sizeof(p),siz…

第五次作業

學習時間新增代碼行博客發表量知識總結 第十周5801HTML5 C和C 一般用于服務端的服務程序開發&#xff0c;硬件編程開發&#xff0c;系統等等大量框架要用到的。JAVA&#xff0c;學好這個可以開發移動設備程序&#xff0c;JSP網頁程序。C#&#xff0c;學了這個可以開發Winform&a…

數字信號處理的fpga實現_FPGA數字信號處理:通信類I/Q信號及產生

大俠好&#xff0c;歡迎來到FPGA技術江湖&#xff0c;江湖偌大&#xff0c;相見即是緣分。大俠可以關注FPGA技術江湖&#xff0c;在“闖蕩江湖”、"行俠仗義"欄里獲取其他感興趣的資源&#xff0c;或者一起煮酒言歡。大俠好&#xff0c;“寧夏李治廷”再一次和各位見…

iic通訊協議

IIC總線 一般串行數據通訊都有時鐘和數據之分,有異步和同步之別. 有單線,雙線和三線等. I2C肯定是2線的(不算地線). I2C協議確實很科學,比3/4線的SPI要好,當然線多通訊速率相對就快了. I2C的原則是: 在SCL1(高電平)時,SDA千萬別忽悠!!! 否則,SDA下跳則"判罰"為&…

使用 Python 切割圖片

剛好我有張 PNG 圖片需要均勻切割&#xff0c;剛好我不會 PhotoShop&#xff0c;剛好我想用 Python 來練練手。 于是擼袖子碼腳本。 import os from PIL import Imagedef splitimage(src, rownum, colnum, dstpath):img Image.open(src)w, h img.sizeif rownum < h and co…

python數據分析知識點_Python數據分析--Pandas知識點(三)

本文主要是總結學習pandas過程中用到的函數和方法, 在此記錄, 防止遺忘. 下面將是在知識點一, 二的基礎上繼續總結. 前面所介紹的都是以表格的形式中展現數據, 下面將介紹Pandas與Matplotlib配合繪制出折線圖, 散點圖, 餅圖, 柱形圖, 直方圖等五大基本圖形. Matplotlib是python…

SPI通訊協議

SPI&#xff1a;高速同步串行口。是一種標準的四線同步雙向串行總線。 SPI&#xff0c;是英語Serial Peripheral interface的縮寫&#xff0c;顧名思義就是串行外圍設備接口。是Motorola首先在其MC68HCXX系列處理器上定義的。SPI接口主要應用在 EEPROM&#xff0c;FLASH&#x…

基于MVVM的知乎日報應用安卓源碼

使用data binding , dagger2 , retrofit2和rxjava實現的&#xff0c;基于MVVM的知乎日報APP運行效果&#xff1a; <ignore_js_op> 使用說明&#xff1a; 項目結構android data binding來實現MVVM。dagger2來完成依賴注入。retrofit2rxjava實現restful的http請求。第三方類…

F#創建者Don Syme談F#設計原則

在.Net Fringe 2016大會上&#xff0c;F#創建者Don Syme談了他對F#現狀的看法以及F#的二元性。F#是以一個為面向對象語言構建的運行時為基礎構建的函數式語言。\\F#是2010年發布的&#xff0c;遵循開源許可協議。F#比.Net更早地踏上了開源之路&#xff0c;C#和.Net在2015年才開…

php簽入html出來的影響seo嗎_搜索引擎優化_SEO必備6大技能+SEO誤區講解!

大家好&#xff0c;我是逆冬&#xff0c;今天來分享一下實戰SEO需要掌握什么樣的技能以及SEO知識誤區&#xff0c;本篇文章僅代表逆冬本人幾年的經驗、不見得適合每一個SEOer!下面就讓逆冬本人來分析一下實戰型SEO到底需要掌握什么技能。第1點&#xff1a;SEO需要不需要熟練掌握…

編寫linux驅動程序步驟

一、建立Linux驅動框架&#xff08;裝載、卸載Linux驅動&#xff09; Linux內核在使用驅動時首先要裝載驅動&#xff0c;在裝載過程中進行一些初始化動作&#xff08;建立設備文件、分配內存等&#xff09;&#xff0c;在驅動程序中需提供相應函數來處理驅動初始化工作&#xf…