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


相关文章
|
4月前
|
存储 运维 Kubernetes
批处理及有状态等应用类型在 K8S 上应该如何配置?
批处理及有状态等应用类型在 K8S 上应该如何配置?
|
1月前
|
Kubernetes 监控 测试技术
在K8S中,如何查看pod状态的详情? 事件显示cpu不足如何处理?
在K8S中,如何查看pod状态的详情? 事件显示cpu不足如何处理?
|
3月前
|
存储 缓存 中间件
启用会话控制
【6月更文挑战第15天】启用会话控制。
24 3
|
4月前
|
Linux 数据安全/隐私保护
HMC配置及操作
HMC配置及操作
50 0
|
4月前
|
弹性计算 运维 Shell
自动配置rsynd
【4月更文挑战第29天】
34 0
SAP S4用于禁用事务代码的操作
禁用事务代码的操作
202 0
|
监控
zabbix配置自动发现主机和自动关联模板
zabbix配置自动发现主机和自动关联模板
343 0
zabbix配置自动发现主机和自动关联模板
SAP 操作,弹出报错 - 已根据规则拒绝服务器触发的操作,是否要查看上个通讯步骤中触发的操作列表 -
SAP 操作,弹出报错 - 已根据规则拒绝服务器触发的操作,是否要查看上个通讯步骤中触发的操作列表 -
SAP 操作,弹出报错 - 已根据规则拒绝服务器触发的操作,是否要查看上个通讯步骤中触发的操作列表 -
|
Web App开发 Linux
【优化】创建安全组时支持同步创建规则
经常听到用户反馈:为什么我的实例SSH不通?为什么部署在ECS实例上的网站无法访问?这类问题多数是由于没有正确配置ECS实例所属安全组的规则。这种情况的场景一般是用户在创建安全组后,忘记了创建规则导致无法访问实例,进而实例无法提供服务。
1438 0