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"); } } }