♻️ feat(新增): 添加方法上的事务注解

This commit is contained in:
bunny 2024-09-05 14:26:31 +08:00
parent 18e6c9adbf
commit 0039f37f8d
7 changed files with 55 additions and 39 deletions

View File

@ -0,0 +1,6 @@
namespace Bunny.Common.Attribute;
[AttributeUsage(AttributeTargets.Method)]
public class TransactionAttribute : System.Attribute
{
}

View File

@ -37,7 +37,7 @@ public class EfCoreContext : DbContext
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
Log.Info("EfCoreContext 数据库连接...");
options.UseSqlServer(DbPath).AddInterceptors(new TransactionInterceptor());
options.UseSqlServer(DbPath);
}
/// <summary>

View File

@ -1,34 +0,0 @@
using Bunny.Common.Exception;
using Bunny.Dao.Common.Constant;
using Microsoft.EntityFrameworkCore.Diagnostics;
namespace Bunny.Common.Context.Database;
public class TransactionInterceptor : SaveChangesInterceptor
{
// 重写 SavingChanges 方法
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
{
// 如果当前上下文存在事务,则直接返回结果
if (eventData.Context!.Database.CurrentTransaction != null) return result;
// 开始数据库事务
using var transaction = eventData.Context.Database.BeginTransaction();
try
{
// 调用基类方法继续保存更改
result = base.SavingChanges(eventData, result);
// 如果保存更改成功,则提交事务
transaction.Commit();
}
catch (System.Exception)
{
// 如果保存更改失败,则回滚事务并抛出自定义异常
transaction.Rollback();
throw new BunnyException(ExceptionConstant.DataBaseError);
}
return result;
}
}

View File

@ -0,0 +1,39 @@
using System.Transactions;
using Bunny.Common.Attribute;
using Bunny.Common.Context;
using log4net;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Bunny.Common.Filter;
public class TransactionIAsyncActionFilter : IAsyncActionFilter
{
private static readonly ILog Log = LogManager.GetLogger(typeof(TransactionIAsyncActionFilter));
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var actionDesc = context.ActionDescriptor as ControllerActionDescriptor;
var hasNotTransactionalAttribute =
actionDesc?.MethodInfo.IsDefined(typeof(TransactionAttribute), false) ?? false;
if (hasNotTransactionalAttribute)
{
await next();
return;
}
using var txScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
var result = await next();
if (result.Exception == null)
{
txScope.Complete();
}
else
{
var errorMessage =
$"执行数据库出错 用户Id[{BaseContext.GetUserId()}] token [{BaseContext.GetToken()}]:{result.Exception}";
Log.Error(errorMessage);
}
}
}

View File

@ -1,4 +1,6 @@
using Bunny.Common.Context.Database;
using Bunny.Common.Attribute;
using Bunny.Common.Context.Database;
using Bunny.Common.Exception;
using Bunny.Common.Utils.Net;
using Bunny.Dao.Common.Result;
using Bunny.Dao.Dto.System;
@ -59,9 +61,9 @@ public class BlogService : IBlogService
/// 批量添加数据
/// </summary>
/// <param name="url"></param>
[Transaction]
public void AddBatchBlogs(string url)
{
using var transaction = DbContext.Database.BeginTransaction();
var list = new List<Blog>();
for (var i = 0; i <= 100; i++)
@ -69,7 +71,7 @@ public class BlogService : IBlogService
DbContext.Blogs.AddRange(list);
DbContext.SaveChanges();
transaction.Commit();
throw new BunnyException("测试事务注解");
}
/// <summary>

View File

@ -32,6 +32,7 @@ public static class ServiceRegistration
{
option.Filters.Add<GlobalExceptionFilter>();
option.Filters.Add<ValidateModelStateAttribute>();
option.Filters.Add<TransactionIAsyncActionFilter>();
option.Filters.Add<AuthorizationFilter>();
});
}

View File

@ -371,4 +371,6 @@ Exception Filter异常过滤器用于处理应用程序中发生的异
7. TypeFilterAttribute
类似于ServiceFilterAttribute但它是通过反射创建过滤器实例不需要过滤器在DI容器中注册。
可以接受参数,用于构造过滤器实例。
可以接受参数,用于构造过滤器实例。
![](https://learn.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters/_static/filter-pipeline-2.png?view=aspnetcore-8.0)