ActionFilter自动事务
1、自动事务
1、数据库事务:要么全部成功、要么全部失败。
2、自动化:启动、提交以及回滚事务。
3、当一段使用EF Core进行数据库操作的代码放到TransactionScope声明的范围中的时候,这段代码就会自动被标记为“支持事务”。
4、TransactionScope实现了IDisposable接口,如果一个TransactionScope的对象没有调用Complete()就执行了Dispose()方法,则事务会被回滚,否则事务就会被提交。
5、TransactionScope还支持嵌套式事务。
6、.NET Core中的TransactionScope不像.NET FX一样有MSDTC分布式事务提升的问题。请使用最终一致性事务
public class MyTransactionScopeFilter : IAsyncActionFilter
{
private readonly ILogger<MyTransactionScopeFilter> _logger;
public MyTransactionScopeFilter(ILogger<MyTransactionScopeFilter> logger)
{
_logger = logger;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
bool hasTransactionalAttribute = false;
if (context.ActionDescriptor is ControllerActionDescriptor)
{
var actionDesc = (ControllerActionDescriptor)context.ActionDescriptor;
hasTransactionalAttribute = actionDesc.MethodInfo
.IsDefined(typeof(NotTransactionalAttribute));
}
if (hasTransactionalAttribute)
{
await next();
return;
}
using var txScope =
new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
var result = await next();
if (result.Exception == null)
{
txScope.Complete();
}
}
2、NotTransactionalAttribute标记
[AttributeUsage(AttributeTargets.Method)]
public class NotTransactionalAttribute:Attribute
{
}
3、对于强制不进行事务控制的Action方法,请标注NotTransactionalAttribute。
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class PersonsController : Controller
{
private readonly StudyContext context;
public PersonsController(StudyContext context)
{
this.context = context;
}
[HttpPost, Route("AddRange")]
[AllowAnonymous]
public async Task<IActionResult> AddRange()
{
await context.AddAsync(new Person
{
Name = "李七夜",
Gender = "男",
Nation = "傣族",
Political = "团员",
IdCard = "8325621525674820",
Address = "云南 昆明 呈贡",
NativePlace = "云南 呈贡",
AccountType = "农村",
Birthday = Convert.ToDateTime("2022-11-25"),
Phone = "60618516726",
QQ = "48818478330",
Email = "48818478330@qq.com",
MaritalStatus = "未婚",
GraduateSchool = "云南民族大学",
Major = "网络工程",
Education = "本科"
});
await context.SaveChangesAsync();
Console.WriteLine("第0条");
await context.AddAsync(new Person
{
Name = "裁决",
Gender = "男",
Nation = "汉族",
Political = "群众",
IdCard = "16345263020651362",
Address = "云南 昆明 官渡",
NativePlace = "云南 官渡",
AccountType = "城镇",
Birthday = Convert.ToDateTime("2022-11-25"),
Phone = "6713050-13413",
QQ = "604949352",
Email = "604949352@163.com",
MaritalStatus = "已婚",
GraduateSchool = "云南师范大学",
Major = "计算机科学与技术",
Education = "本科"
});
await context.SaveChangesAsync();
Console.WriteLine("第1条");
return Json(new { code = 200, message = "成功!" });
}
[HttpPost, Route("Add")]
[AllowAnonymous]
[NotTransactional]
public async Task<IActionResult> Add([FromBody] Person people)
{
using TransactionScope scope = new TransactionScope();
await context.AddAsync(people);
await context.SaveChangesAsync();
scope.Complete();
return Json(new { code = 200, message = "成功!" });
}
}
4、依赖注入
builder.Services.Configure<MvcOptions>(options =>
{
options.Filters.Add<MyTransactionScopeFilter>();
})