操作筛选器的 1 个应用实例:自动启用事务

简介: 操作筛选器的 1 个应用实例:自动启用事务

前言

在数据库操作过程中,有一个概念是绕不开的,那就是事务。

事务能够确保一系列数据库操作要么全部成功提交,要么全部失败回滚,保证数据的一致性和完整性。

在 Asp.Net Core Web API 中,我们可以使用操作筛选器给所有的数据库操作 API 加上事务控制,省心又省力,效果还很好。

看看 Step By Step 步骤是如何实现上述功能的。

Step By Step 步骤

  1. 创建一个 ASP.NET Core Web API 项目
  2. 引用 EF Core 项目 BooksEFCore
  1. 打开 appsettings.json,添加数据库连接串
{
  "Logging": {
  "LogLevel": {
    "Default": "Information",
    "Microsoft.AspNetCore": "Warning"
  }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
  "Default": "Server=(localdb)\\mssqllocaldb;Database=TestDB;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

4.创建一个自定义的 Attribute,用于给无需启用事务控制的操作方法

[AttributeUsage(AttributeTargets.Method)]
public class NotTransactionalAttribute:Attribute
{
}

5.编写自定义的操作筛选器 TransactionScopeFilter,用于自动启用事务控制(留意注释

using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Reflection;
using System.Transactions;
public class TransactionScopeFilter : IAsyncActionFilter
{
  public async Task OnActionExecutionAsync(
    ActionExecutingContext context, 
    ActionExecutionDelegate next)
  {
    bool hasNotTransactionalAttribute = false;
    if (context.ActionDescriptor is ControllerActionDescriptor)
    {
      var actionDesc = (ControllerActionDescriptor)context.ActionDescriptor;
      //判断操作方法上是否标注了NotTransactionalAttribute
      hasNotTransactionalAttribute = actionDesc.MethodInfo.IsDefined(typeof(NotTransactionalAttribute));
    }
    //如果操作方法标注了NotTransactionalAttribute,直接执行操作方法
    if (hasNotTransactionalAttribute)
    {
      await next();
      return;
    }
    //如果操作方法没有标注NotTransactionalAttribute,启用事务
    using var txScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
    var result = await next();
    if (result.Exception == null)
    {
      txScope.Complete();
    }
  }
}

6.打开 Program.cs,注册这个操作筛选器

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 注册数据库服务
builder.Services.AddDbContext<MyDbContext>(opt => {
  string connStr = builder.Configuration.GetConnectionString("Default");
  opt.UseSqlServer(connStr);
});
// 注册自动启用事务过滤器
builder.Services.Configure<MvcOptions>(opt => { 
  opt.Filters.Add<TransactionScopeFilter>();
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
  app.UseSwagger();
  app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

7.开控制器,增加一个用于测试的操作方法(留意注释

using Microsoft.AspNetCore.Mvc;
namespace 自动启用事务的筛选器.Controllers
{
  [ApiController]
  [Route("[controller]/[action]")]
  public class TestController : ControllerBase
  {
    private readonly MyDbContext dbCtx;
    public TestController(MyDbContext dbCtx)
    {
      this.dbCtx = dbCtx;
    }
    [HttpPost]
    public async Task Save()
    {
      dbCtx.Books.Add(new Book { Id = Guid.NewGuid(), Name = "1", Price = 1 });
      await dbCtx.SaveChangesAsync();
      dbCtx.Books.Add(new Book { Id = Guid.NewGuid(), Name = "2", Price = 2 });
      await dbCtx.SaveChangesAsync();
      // 以上代码能够正确地插入两条数据
      // 如果启用以下代码抛出异常,将不会插入数据
      // 说明事务起作用,数据被回滚了
      // throw new Exception();
    }
  }
}


相关文章
|
存储 监控 安全
基于【国基北盛】云基础架构平台软件搭建openstack私有云平台(先电V2.4版本)(上)
基于【国基北盛】云基础架构平台软件搭建openstack私有云平台(先电V2.4版本)
1607 0
基于【国基北盛】云基础架构平台软件搭建openstack私有云平台(先电V2.4版本)(上)
|
算法 搜索推荐 C++
【C++】sort()、stable_sort()和partial_sort()排序函数详解
【C++】sort()、stable_sort()和partial_sort()排序函数详解
669 0
|
消息中间件 存储 Java
使用Java构建实时数据处理流程
使用Java构建实时数据处理流程
|
KVM 虚拟化
KVM虚拟机的克隆
这篇文章介绍了如何使用KVM虚拟机进行完整克隆和链接克隆,包括手动克隆和使用virt-clone工具克隆的方法,以及如何编写脚本来实现自动化克隆和删除虚拟机。
420 3
KVM虚拟机的克隆
|
前端开发 小程序 Java
java基础:map遍历使用;java使用 Patten 和Matches 进行正则匹配;后端传到前端展示图片三种情况,并保存到手机
这篇文章介绍了Java中Map的遍历方法、使用Pattern和matches进行正则表达式匹配,以及后端向前端传输图片并保存到手机的三种情况。
155 1
|
JavaScript 前端开发 数据库
优化后端性能:如何使用异步编程提升系统响应速度
异步编程已成为现代后端系统性能优化的重要策略。通过避免阻塞操作,异步编程可以显著提高系统的响应速度和并发处理能力。本文章深入探讨了异步编程的基本概念,比较了常见的异步编程模型,并通过实际案例演示如何在Node.js和Python中实现异步操作,以提升系统性能。
|
Java Spring
解决Springboot集成ElasticSearch 报错:A bean with that name has already been defined in null and overriding
解决Springboot集成ElasticSearch 报错:A bean with that name has already been defined in null and overriding
454 2
|
Web App开发 Java Apache
java.lang.NumberFormatException: For input string: &quot;undefined&quot;
在将字符串转换为数字时导致此错误,解决此问题的思路:1、添加Try catch语句,2、判断字符串是否为数字,将介绍java中判断字符串是否为数字的方法的几种方法。 完整错误信息: java.
2356 0
|
前端开发 JavaScript Java
验证码这样做,瞬间高出一个逼格
验证码这样做,瞬间高出一个逼格
493 0
验证码这样做,瞬间高出一个逼格
下一篇
开通oss服务