操作筛选器的 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();
    }
  }
}


相关文章
|
6月前
|
存储 运维 Kubernetes
批处理及有状态等应用类型在 K8S 上应该如何配置?
批处理及有状态等应用类型在 K8S 上应该如何配置?
|
1月前
|
Kubernetes 监控 容器
|
6月前
|
Linux 数据安全/隐私保护
HMC配置及操作
HMC配置及操作
102 0
|
6月前
|
存储
Qt更新组件出现(“要继续此操作,至少需要一个有效且已启用的储存库”)
Qt更新组件出现(“要继续此操作,至少需要一个有效且已启用的储存库”)
325 0
Qt更新组件出现(“要继续此操作,至少需要一个有效且已启用的储存库”)
|
6月前
|
弹性计算 运维 Shell
自动配置rsynd
【4月更文挑战第29天】
43 0
|
消息中间件 架构师 数据处理
处理数据时点按钮,数据完数据时会自动执行的问题
处理数据时点按钮,数据完数据时会自动执行的问题
|
存储 数据库 Nacos
【Sentinel】授权规则与规则持久化
【Sentinel】授权规则与规则持久化
466 0
【Sentinel】授权规则与规则持久化
|
监控
zabbix配置自动发现主机和自动关联模板
zabbix配置自动发现主机和自动关联模板
368 0
zabbix配置自动发现主机和自动关联模板
SAP 操作,弹出报错 - 已根据规则拒绝服务器触发的操作,是否要查看上个通讯步骤中触发的操作列表 -
SAP 操作,弹出报错 - 已根据规则拒绝服务器触发的操作,是否要查看上个通讯步骤中触发的操作列表 -
SAP 操作,弹出报错 - 已根据规则拒绝服务器触发的操作,是否要查看上个通讯步骤中触发的操作列表 -