♻️ feat(新增): 添加方法上的事务注解
This commit is contained in:
parent
18e6c9adbf
commit
0039f37f8d
|
@ -0,0 +1,6 @@
|
|||
namespace Bunny.Common.Attribute;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class TransactionAttribute : System.Attribute
|
||||
{
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -32,6 +32,7 @@ public static class ServiceRegistration
|
|||
{
|
||||
option.Filters.Add<GlobalExceptionFilter>();
|
||||
option.Filters.Add<ValidateModelStateAttribute>();
|
||||
option.Filters.Add<TransactionIAsyncActionFilter>();
|
||||
option.Filters.Add<AuthorizationFilter>();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue