using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Reflection;
using System.Threading.Tasks;
using System.Transactions;
namespace Utility
{
///
/// 工作单元配置特性
///
[AttributeUsage(AttributeTargets.Method)]
public sealed class UnitOfWorkAttribute : Attribute, IAsyncActionFilter, IAsyncPageFilter, IOrderedFilter
{
///
/// 确保事务可用
/// 此方法为了解决静态类方式操作数据库的问题
///
public bool EnsureTransaction { get; set; } = false;
///
/// 是否使用分布式环境事务
///
public bool UseAmbientTransaction { get; set; } = false;
///
/// 分布式环境事务范围
///
/// 为 true 有效
public TransactionScopeOption TransactionScope { get; set; } = TransactionScopeOption.Required;
///
/// 分布式环境事务隔离级别
///
/// 为 true 有效
public IsolationLevel TransactionIsolationLevel { get; set; } = IsolationLevel.ReadCommitted;
///
/// 分布式环境事务超时时间
///
/// 单位秒
public int TransactionTimeout { get; set; } = 0;
///
/// 支持分布式环境事务异步流
///
/// 为 true 有效
public TransactionScopeAsyncFlowOption TransactionScopeAsyncFlow { get; set; } = TransactionScopeAsyncFlowOption.Enabled;
///
/// MiniProfiler 分类名
///
private const string MiniProfilerCategory = "unitOfWork";
///
/// 过滤器排序
///
private const int FilterOrder = 9999;
///
/// 排序属性
///
public int Order => FilterOrder;
///
/// 构造函数
///
public UnitOfWorkAttribute()
{
}
///
/// 构造函数
///
///
public UnitOfWorkAttribute(bool ensureTransaction)
{
EnsureTransaction = ensureTransaction;
}
///
/// 拦截请求
///
/// 动作方法上下文
/// 中间件委托
///
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// 获取动作方法描述器
var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
var method = actionDescriptor.MethodInfo;
// 创建分布式环境事务
(var transactionScope, var logger) = CreateTransactionScope(context);
try
{
// 打印工作单元开始消息
Console.WriteLine("Beginning (Ambient)");
// 开始事务
BeginTransaction(context, method, out var _unitOfWork, out var unitOfWorkAttribute);
// 获取执行 Action 结果
var resultContext = await next();
// 提交事务
CommitTransaction(context, _unitOfWork, unitOfWorkAttribute, resultContext);
// 提交分布式环境事务
if (resultContext.Exception == null)
{
transactionScope?.Complete();
// 打印事务提交消息
if (UseAmbientTransaction) Console.WriteLine("Completed (Ambient)");
}
else
{
// 打印事务回滚消息
if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)");
logger.LogError(resultContext.Exception, "Transaction Failed.");
}
}
catch (Exception ex)
{
logger.LogError(ex, "Transaction Failed.");
// 打印事务回滚消息
if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)");
throw;
}
finally
{
transactionScope?.Dispose();
}
}
///
/// 模型绑定拦截
///
///
///
public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
{
return Task.CompletedTask;
}
///
/// 拦截请求
///
///
///
///
public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
// 获取动作方法描述器
var method = context.HandlerMethod?.MethodInfo;
// 处理 Blazor Server
if (method == null)
{
_ = await next.Invoke();
return;
}
// 创建分布式环境事务
(var transactionScope, var logger) = CreateTransactionScope(context);
try
{
// 打印工作单元开始消息
if (UseAmbientTransaction) Console.WriteLine("Beginning (Ambient)");
// 开始事务
BeginTransaction(context, method, out var _unitOfWork, out var unitOfWorkAttribute);
// 获取执行 Action 结果
var resultContext = await next.Invoke();
// 提交事务
CommitTransaction(context, _unitOfWork, unitOfWorkAttribute, resultContext);
// 提交分布式环境事务
if (resultContext.Exception == null)
{
transactionScope?.Complete();
// 打印事务提交消息
if (UseAmbientTransaction) Console.WriteLine("Completed (Ambient)");
}
else
{
// 打印事务回滚消息
if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)");
logger.LogError(resultContext.Exception, "Transaction Failed.");
}
}
catch (Exception ex)
{
logger.LogError(ex, "Transaction Failed.");
// 打印事务回滚消息
if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)");
throw;
}
finally
{
transactionScope?.Dispose();
}
}
///
/// 创建分布式环境事务
///
///
///
private (TransactionScope, ILogger) CreateTransactionScope(FilterContext context)
{
// 是否启用分布式环境事务
var transactionScope = UseAmbientTransaction
? new TransactionScope(TransactionScope,
new TransactionOptions { IsolationLevel = TransactionIsolationLevel, Timeout = TransactionTimeout > 0 ? TimeSpan.FromSeconds(TransactionTimeout) : default }
, TransactionScopeAsyncFlow)
: default;
// 创建日志记录器
var logger = context.HttpContext.RequestServices.GetRequiredService>();
return (transactionScope, logger);
}
///
/// 开始事务
///
///
///
///
///
private static void BeginTransaction(FilterContext context, MethodInfo method, out IUnitOfWork _unitOfWork, out UnitOfWorkAttribute unitOfWorkAttribute)
{
// 解析工作单元服务
_unitOfWork = context.HttpContext.RequestServices.GetRequiredService();
// 获取工作单元特性
unitOfWorkAttribute = method.GetCustomAttribute();
// 调用开启事务方法
_unitOfWork.BeginTransaction(context, unitOfWorkAttribute);
// 打印工作单元开始消息
if (!unitOfWorkAttribute.UseAmbientTransaction) Console.WriteLine("Beginning");
}
///
/// 提交事务
///
///
///
///
///
private static void CommitTransaction(FilterContext context, IUnitOfWork _unitOfWork, UnitOfWorkAttribute unitOfWorkAttribute, FilterContext resultContext)
{
// 获取动态结果上下文
dynamic dynamicResultContext = resultContext;
if (dynamicResultContext.Exception == null)
{
// 调用提交事务方法
_unitOfWork.CommitTransaction(resultContext, unitOfWorkAttribute);
}
else
{
// 调用回滚事务方法
_unitOfWork.RollbackTransaction(resultContext, unitOfWorkAttribute);
}
// 调用执行完毕方法
_unitOfWork.OnCompleted(context, resultContext);
// 打印工作单元结束消息
if (!unitOfWorkAttribute.UseAmbientTransaction) Console.WriteLine("Ending");
}
}
}