知識全聚集 .Net Core 技術突破 | 簡單說說工作單元


知識全聚集 .Net Core 技術突破 | 簡單說說工作單元

教程

01 | 模塊化方案一

02 | 模塊化方案二

其他教程預覽

分庫分表項目實戰教程

Git地址: https://github.com/MrChuJiu/EasyLogger

01 | 前言

02 | 簡單的分庫分表設計

03 | 控制反轉搭配簡單業務

04 | 強化設計方案

05 | 完善業務自動創建數據庫

06 | 最終篇-通過AOP自動連接數據庫-完成日志業務

從10.1到現在都太忙了,好久沒更新文章了,也主要因為 工作單元這個東西我也是不知道該怎么才能講明白,很多東西需要靠自己的一個理解。

今天可以稍微講一下,看完這篇文章在對應源碼去看,我覺得就會舒服很多。

本文章請一定要配合源碼食用,注釋都在源碼里寫好了。

https://github.com/MrChuJiu/Easy.Core.Flow

簡單說說運行路線

工作單元的開始入口是從 AspNetCoreUowMiddleware 中間件開始的

1.判斷是否匹配到了路由地址
2.判斷是否攜帶 UnitOfWorkAttribute 屬性 如果攜帶了獲取屬性值
3.判斷是否攜帶了屬性中禁用工作單元,如果是直接跳出該中間件
4.獲取鏈接字符串名稱 啟動一個工作單元包裹當前中間件
5.接口操作結束后 判斷相應狀態提交工作單元

先看主要的文件和描述

接口文件 描述 實現
IUnitOfWork 工作單元實例 UnitOfWorkBase
ICurrentUnitOfWorkProvider 工作單元提供者 AsyncLocalCurrentUnitOfWorkProvider
IUnitOfWorkManager 工作單元管理器 DefaultUnitOfWorkManager

一個基礎的EF工作單元操作(記住這個概念我們接下來看代碼)

var unitOfWorkManager = scopeServiceProvider.GetService<IUnitOfWorkManager>();
using (var uow = unitOfWorkManager.Begin())
{
    var appContext = unitOfWorkManager.Current.GetDbContext<AppDbContext>();
    var user = new User();
    user.Creator = "Creator";
    appContext.Users.Add(user);
    await uow.CompleteAsync();
}
表面通過 工作單元管理器創建一個工作單元實例  IUnitOfWork  實例
內部:   工作單元管理器中 將 工作單元配置參數(事務級別/事務范圍/超時/事件/連接字符串顯示名稱) 存放到工作單元提供者后續 提供給具體實現進行使用

IUnitOfWorkManager 工作單元管理器


Begin() 方法返回的是一個類型為 IUnitOfWorkCompleteHandle 工作單元事件處理器 主要看繼承他的方法

一:InnerUnitOfWorkCompleteHandle

主要調用 Complete()/CompleteAsync() 會將 _isCompleteCalled 置為 true,然后在 Dispose() 方法內會進行檢測,為 faslse 的話直接拋出異常。

可以看到在 InnerUnitOfWorkCompleteHandle 內部並不會真正地調用 DbContext.SaveChanges() 進行數據保存。
該類可以在 Begin() 方法中看到在創建 UOW 對象的時候,他在內部進行了一個判斷,如果不存在外部工作單元的情況下才會創建 InnerUnitOfWorkCompleteHandle 對象,否則是解析的一個 IUnitOfWork 對象。

請下載代碼調試

      using (var scope = app.ApplicationServices.CreateScope())
                {

                    var scopeServiceProvider = scope.ServiceProvider;

                    var unitOfWorkManager = scopeServiceProvider.GetService<IUnitOfWorkManager>();
                   

                    using (var outerUOW1 = unitOfWorkManager.Begin())  // 這里返回的是 IOC 解析出的 IUnitOfWork
                    {
                        var appContext1 = unitOfWorkManager.Current.GetDbContext<AppDbContext>();

                        var user1 = new User();
                        user1.Creator = "Creator1111";
                        appContext1.Users.Add(user1);
                        using (var innerUOW2 = unitOfWorkManager.Begin())  // 內部 UOW
                        {
                            var appContext2 = unitOfWorkManager.Current.GetDbContext<AppDbContext>();
                            var user2 = new User();
                            user2.Creator = "Creator222";
                            appContext2.Users.Add(user2);

                            using (var innerUOW3 = unitOfWorkManager.Begin())  // 內部 UOW
                            {
                                var appContext3 = unitOfWorkManager.Current.GetDbContext<AppDbContext>();

                                var user3 = new User();
                                user3.Creator = "Creator333";
                                appContext3.Users.Add(user3);
                                await innerUOW3.CompleteAsync();
                            }
                            await innerUOW2.CompleteAsync();
                        }
                        await outerUOW1.CompleteAsync();
                    }
                }

二:IUnitOfWork

Id 是使用的 Guid 生成的,用於標識每個工作單元。
Outer 則是當前 UOW 對象的引用對象
Begin 根據工作單元選項創建(各個ORM啟動工作單元的方式不同,讓他們各自去繼承實現)
EfCoreUnitOfWork -> UnitOfWorkBase -> IUnitOfWork

ICurrentUnitOfWorkProvider 工作單元提供者

我們在 UnitOfWorkManager.Begin() 方法最后一行 _currentUnitOfWorkProvider.Current = uow;
_currentUnitOfWorkProvider 的實現在 AsyncLocalCurrentUnitOfWorkProvider 內部,其作用是維護一個 UOW 鏈 確保當前的工作單元始終是最新的

重點是 value.Outer = AsyncLocalUow.Value.UnitOfWork; = IUnitOfWork.Outer

電腦截圖有限最好下載代碼去對着文章自己過一下

EfCoreUnitOfWork 落實到EFCore實際處理

EfCoreUnitOfWork -> UnitOfWorkBase -> IUnitOfWork

隨隨便便結尾

IUnitOfWork、ICurrentUnitOfWorkProvider、IUnitOfWorkManager 實現原理

EfCoreUnitOfWork 具體的實現

其它類具體的解釋我都寫了注釋,自己下載看吧,

鳴謝

玩雙截棍的熊貓

源地址:https://github.com/rivenfx/Framework

我只能說:ABP牛皮!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM