简单介绍工作单元

工作单元模式:用来维护一个已经被业务事务修改(CURD操作)的业务对象列表。工作单元模式负责协调这些修改的持久化工作以及所有标记的并发问题。采用工作单元模式带来的好处是能够保证数据的完整性。如果在持久化一系列业务对象的过程中出现问题,则将所有的修改回滚,以保证数据始终处于有效状态。简单来说,工作单元模式就是把业务对象的持久化由工作单元实现类进行统一管理。而不想之前那样,分布在每个具体的仓储类中,这样就可以达到一系列业务对象的统一管理,不至于在每个业务对象中出现统一的提交和回滚业务逻辑,实现代码最大化重用。

简单概括就是:对某个业务操作,比如银行的进出账的业务对象(进账对象,出账对象)进行统一管理,使它们不需要在自己的repository中提交(commit),放在工作单元中做持久化工作。

一.创建工作单元依赖接口

/// <summary>
/// 工作单元依赖接口
/// </summary>
public interface IUnitOfWork
{
	/// <summary>
	/// 开启工作单元处理
	/// </summary>
	/// <param name="context"></param>
	/// <param name="unitOfWork"></param>
	void BeginTransaction(ActionExecutingContext context);

	/// <summary>
	/// 提交工作单元处理
	/// </summary>
	/// <param name="resultContext"></param>
	/// <param name="unitOfWork"></param>
	void CommitTransaction(ActionExecutedContext resultContext);

	/// <summary>
	/// 回滚工作单元处理
	/// </summary>
	/// <param name="resultContext"></param>
	/// <param name="unitOfWork"></param>
	void RollbackTransaction(ActionExecutedContext resultContext);

	/// <summary>
	/// 执行完毕(无论成功失败)
	/// </summary>
	/// <param name="context"></param>
	/// <param name="resultContext"></param>
	void OnCompleted(ActionExecutingContext context, ActionExecutedContext resultContext);
}

二.创建工作单元实现,继承工作单元接口

/// <summary>
/// 工作单元的实现
/// </summary>
public class SqlSugarUnitOfWork : IUnitOfWork
{
	/// <summary>
	/// SqlSugar委托
	/// </summary>
	private readonly ISqlSugarClient _sqlSugarClient;
	/// <summary>
	/// 构造函数
	/// </summary>
	/// <param name="sqlSugarClient">SqlSugar委托</param>

	public SqlSugarUnitOfWork(ISqlSugarClient sqlSugarClient)
	{
		this._sqlSugarClient = sqlSugarClient;
	}
	/// <summary>
	/// 开启事务
	/// </summary>
	/// <param name="context">执行中</param>
	public void BeginTransaction(ActionExecutingContext context)
	{
		_sqlSugarClient.AsTenant().BeginTran();
	}
	/// <summary>
	/// 提交事务
	/// </summary>
	/// <param name="resultContext">执行结果上下文</param>

	public void CommitTransaction(ActionExecutedContext resultContext)
	{
		_sqlSugarClient.AsTenant().CommitTran();
	}
	/// <summary>
	/// 处理事务
	/// </summary>
	/// <param name="context">执行中</param>
	/// <param name="resultContext">执行结果上下文</param>

	public void OnCompleted(ActionExecutingContext context, ActionExecutedContext resultContext)
	{
		_sqlSugarClient.Dispose();
	}
	/// <summary>
	/// 回滚事务
	/// </summary>
	/// <param name="resultContext">执行结果上下文</param>
	public void RollbackTransaction(ActionExecutedContext resultContext)
	{
		_sqlSugarClient.AsTenant().RollbackTran();
	}
}

三.在启动类Program中注册工作单元接口和实现

//注册UnitOfWork
builder.Services.AddTransient<IUnitOfWork, SqlSugarUnitOfWork>();

四.创建工作单元特性

/// <summary>
	/// 工作单元配置特性
	/// </summary>
	[AttributeUsage(AttributeTargets.Method)]
	public class UnitOfWorkAttribute : Attribute { }

五.配置工作单元过滤器

/// <summary>
/// 工作单元过滤器
/// </summary>
public class UnitOfWorkFilter:IAsyncActionFilter,IOrderedFilter
{
	private readonly ILogger<UnitOfWorkFilter> _logger;
	/// <summary>
	/// 构造函数
	/// </summary>
	/// <param name="logger">日志</param>
	public UnitOfWorkFilter(ILogger<UnitOfWorkFilter> logger)
	{
		this._logger = logger;
	}
	/// <summary>
	/// 过滤器排序
	/// </summary>
	internal const int FilterOrder = 999;

	/// <summary>
	/// 排序属性
	/// </summary>
	public int Order => FilterOrder;

	/// <summary>
	/// 拦截请求
	/// </summary>
	/// <param name="context">动作方法上下文</param>
	/// <param name="next">中间件委托</param>
	public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
	{
		// 获取动作方法描述器
		var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
		var method = actionDescriptor.MethodInfo;

		// 获取请求上下文
		var httpContext = context.HttpContext;

		// 如果没有定义工作单元过滤器,则跳过
		if (!method.IsDefined(typeof(UnitOfWorkAttribute), true))
		{
			// 调用方法
			_ = await next();

			return;
		}

		// 打印工作单元开始消息
		_logger.LogInformation($@"{nameof(UnitOfWorkFilter)} Beginning");

		// 解析工作单元服务
		var _unitOfWork = httpContext.RequestServices.GetRequiredService<IUnitOfWork>();

		// 调用开启事务方法
		_unitOfWork.BeginTransaction(context);

		// 获取执行 Action 结果
		var resultContext = await next();

		if (resultContext == null || resultContext.Exception == null)
		{
			// 调用提交事务方法
			_unitOfWork.CommitTransaction(resultContext);
		}
		else
		{
			// 调用回滚事务方法
			_unitOfWork.RollbackTransaction(resultContext);
		}

		// 调用执行完毕方法
		_unitOfWork.OnCompleted(context, resultContext);

		// 打印工作单元结束消息  
		_logger.LogInformation($@"{nameof(UnitOfWorkFilter)} Ending");

	}
}

六.将配置好的过滤器添加进通信管道(启动类Program)

builder.Services.AddControllers(x =>
{
    //添加 工作单元过滤器
    x.Filters.Add<UnitOfWorkFilter>();
});

配置完成

七.在需要调用UnitOfWork的接口上添加特性[UnitOfWork]特性正常调用就可以了