From 0039f37f8dde3a70dd0054b3089afba49a2e2899 Mon Sep 17 00:00:00 2001
From: bunny <1319900154@qq.com>
Date: Thu, 5 Sep 2024 14:26:31 +0800
Subject: [PATCH] =?UTF-8?q?:recycle:=20feat(=E6=96=B0=E5=A2=9E):=20?=
=?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B9=E6=B3=95=E4=B8=8A=E7=9A=84=E4=BA=8B?=
=?UTF-8?q?=E5=8A=A1=E6=B3=A8=E8=A7=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Attribute/TransactionAttribute.cs | 6 +++
.../Context/Database/EFCoreContext.cs | 2 +-
.../Database/TransactionInterceptor.cs | 34 ----------------
.../Filter/TransactionIAsyncActionFilter.cs | 39 +++++++++++++++++++
Bunny.Service/IService/Service/BlogService.cs | 8 ++--
.../Configuration/ServiceRegistration.cs | 1 +
Bunny.WebApi/ReadMe/ReadMe.md | 4 +-
7 files changed, 55 insertions(+), 39 deletions(-)
create mode 100644 Bunny.Common/Attribute/TransactionAttribute.cs
delete mode 100644 Bunny.Common/Context/Database/TransactionInterceptor.cs
create mode 100644 Bunny.Common/Filter/TransactionIAsyncActionFilter.cs
diff --git a/Bunny.Common/Attribute/TransactionAttribute.cs b/Bunny.Common/Attribute/TransactionAttribute.cs
new file mode 100644
index 0000000..0a01fc1
--- /dev/null
+++ b/Bunny.Common/Attribute/TransactionAttribute.cs
@@ -0,0 +1,6 @@
+namespace Bunny.Common.Attribute;
+
+[AttributeUsage(AttributeTargets.Method)]
+public class TransactionAttribute : System.Attribute
+{
+}
\ No newline at end of file
diff --git a/Bunny.Common/Context/Database/EFCoreContext.cs b/Bunny.Common/Context/Database/EFCoreContext.cs
index 5b0e066..4a0af4f 100644
--- a/Bunny.Common/Context/Database/EFCoreContext.cs
+++ b/Bunny.Common/Context/Database/EFCoreContext.cs
@@ -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);
}
///
diff --git a/Bunny.Common/Context/Database/TransactionInterceptor.cs b/Bunny.Common/Context/Database/TransactionInterceptor.cs
deleted file mode 100644
index 9c3a68b..0000000
--- a/Bunny.Common/Context/Database/TransactionInterceptor.cs
+++ /dev/null
@@ -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 SavingChanges(DbContextEventData eventData, InterceptionResult 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;
- }
-}
\ No newline at end of file
diff --git a/Bunny.Common/Filter/TransactionIAsyncActionFilter.cs b/Bunny.Common/Filter/TransactionIAsyncActionFilter.cs
new file mode 100644
index 0000000..4cb11f2
--- /dev/null
+++ b/Bunny.Common/Filter/TransactionIAsyncActionFilter.cs
@@ -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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bunny.Service/IService/Service/BlogService.cs b/Bunny.Service/IService/Service/BlogService.cs
index fada6d6..52d2155 100644
--- a/Bunny.Service/IService/Service/BlogService.cs
+++ b/Bunny.Service/IService/Service/BlogService.cs
@@ -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
/// 批量添加数据
///
///
+ [Transaction]
public void AddBatchBlogs(string url)
{
- using var transaction = DbContext.Database.BeginTransaction();
var list = new List();
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("测试事务注解");
}
///
diff --git a/Bunny.WebApi/Configuration/ServiceRegistration.cs b/Bunny.WebApi/Configuration/ServiceRegistration.cs
index 58dfa3d..8de2448 100644
--- a/Bunny.WebApi/Configuration/ServiceRegistration.cs
+++ b/Bunny.WebApi/Configuration/ServiceRegistration.cs
@@ -32,6 +32,7 @@ public static class ServiceRegistration
{
option.Filters.Add();
option.Filters.Add();
+ option.Filters.Add();
option.Filters.Add();
});
}
diff --git a/Bunny.WebApi/ReadMe/ReadMe.md b/Bunny.WebApi/ReadMe/ReadMe.md
index 9f3ab02..a789827 100644
--- a/Bunny.WebApi/ReadMe/ReadMe.md
+++ b/Bunny.WebApi/ReadMe/ReadMe.md
@@ -371,4 +371,6 @@ Exception Filter(异常过滤器):用于处理应用程序中发生的异
7. TypeFilterAttribute
类似于ServiceFilterAttribute,但它是通过反射创建过滤器实例,不需要过滤器在DI容器中注册。
- 可以接受参数,用于构造过滤器实例。
\ No newline at end of file
+ 可以接受参数,用于构造过滤器实例。
+
+![](https://learn.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters/_static/filter-pipeline-2.png?view=aspnetcore-8.0)
\ No newline at end of file