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


相关文章
SAP 操作,弹出报错 - 已根据规则拒绝服务器触发的操作,是否要查看上个通讯步骤中触发的操作列表 -
SAP 操作,弹出报错 - 已根据规则拒绝服务器触发的操作,是否要查看上个通讯步骤中触发的操作列表 -
SAP 操作,弹出报错 - 已根据规则拒绝服务器触发的操作,是否要查看上个通讯步骤中触发的操作列表 -
|
9月前
|
SQL JSON 监控
无需重启应用,动态采集任意点位日志
借助日志治理的现有能力,我们能够在不重启应用的前提下,动态采集任意点位信息,同时由于日志治理在采集信息时会引入链路信息,在分析复杂调用问题时能够起到很好的效果。
124 0
无需重启应用,动态采集任意点位日志
|
Web App开发 Linux
【优化】创建安全组时支持同步创建规则
经常听到用户反馈:为什么我的实例SSH不通?为什么部署在ECS实例上的网站无法访问?这类问题多数是由于没有正确配置ECS实例所属安全组的规则。这种情况的场景一般是用户在创建安全组后,忘记了创建规则导致无法访问实例,进而实例无法提供服务。
1481 0
[20170629]带过滤的复制项UI操作导致订阅全部初始化问题
[问题] 带过滤的复制项UI操作导致订阅全部初始化,但是想不全部初始化,只初始化对应的复制项   [解决] 1.如果修改过滤项,可以直接执行,然后生成快照: exec sp_articlefilter @publication = N'testdb', @article = N'tablea' ...
855 0
|
9月前
|
弹性计算 运维 Shell
自动配置rsynd
【4月更文挑战第29天】
55 0

热门文章

最新文章