知识全聚集 .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牛皮!!!

原文地址:https://www.cnblogs.com/MrChuJiu/p/13948902.html