.Net Core Action过滤器使用实例(自动启用事务)

基于前面对Action Filter的介绍,本节通过实例来说明其用法。

.Net Core自定义Action过滤器

数据库事务有一个非常重要的特性,那就是“原子性”,它保证了我们对数据库的多个操作要么全部成功、要么全部失败,进而帮助我们保证业务数据的正确性。

下面代码将实现一个对于数据库操作的自动启用事务的操作筛选器。

使用TransactionScope简化事务代码的编写,TransactionScope是.Net中用来标记一段支持事务的代码的类。EF Core对TransactionScope提供了天然的支持,当一段使用EF Core进行数据库操作的代码放到TransactionScope声明的范围中的时候,这段代码就会自动被标记为“支持事务”。

大多数情况下,操作方法都需要有事务,当一个操作方法不需要自动启用事务控制时,可以给这些操作方法添加一个自定义的NotTransactionalAttribute特性。

NotTransactionalAttribute.cs代码如下:

    /// <summary>
    /// 自定义特性,在不需要自动启用事务控制的方法上添加该特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Method)]
    public class NotTransactionalAttribute : Attribute
    {
    }

编写过滤器TransactionScopeFilter,代码如下:

using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Reflection;
using System.Transactions;

namespace CoreWebApi3
{
    /// <summary>
    /// 自动启用事务的操作筛选器
    /// </summary>
    public class TransactionScopeFilter : IAsyncActionFilter
    {
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            //判断操作方法上是否标记了NotTransactionalAttribute
            bool hasNotTransactionalAttribute = false;
            if (context.ActionDescriptor is ControllerActionDescriptor)
            {
                var actionDesc = (ControllerActionDescriptor)context.ActionDescriptor;
                hasNotTransactionalAttribute = actionDesc.MethodInfo.IsDefined(typeof(NotTransactionalAttribute));
            }

            //如果标记了,则直接执行next
            if (hasNotTransactionalAttribute)
            {
                await next();
                return;
            }

            using (var txScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
            {
                var result = await next();
                if (result.Exception == null)//操作方法执行没有异常
                {
                    txScope.Complete();//提交事务
                }
            }

           

        }
    }
}

在Program.cs中注册TransactionScopeFilter:

//设置全局的筛选器
builder.Services.Configure<MvcOptions>(option =>
{
    option.Filters.Add<TransactionScopeFilter>();
});

注册代码要写在builder.Build()之前。

最后,在EF CORE插入数据的代码中插入记录:

        [HttpPost]
        public async Task Save() {
            dbCtx.Book.Add(new Book { Id = Guid.NewGuid(), Name = "1", Price = 1 });
            await dbCtx.SaveChangeAsync();

            dbCtx.Book.Add(new Book { Id = Guid.NewGuid(), Name = "2", Price = 2 });
            await dbCtx.SaveChangeAsync();
        }

上面的代码能够正确的插入两条数据。如果在第一个SaveChangeAsync下面加入一行throw new Exception() 来抛出异常,再次执行SaveChangeAsync方法之后,就会发现数据库中没有插入记录。这说明第一个SaveChangeAsync执行后,虽然实现了插入数据,但是由于事务回滚,因此被插入的数据也被回滚了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在ASP.NET Core中,可以通过编写过滤器来实现在请求处理过程中插入自定义逻辑。下面是编写过滤器的步骤: 1. 创建一个过滤器类:可以创建一个继承自`IFilterMetadata`接口的类,或者继承自`Attribute`类的特性类,来定义过滤器的逻辑。 2. 实现过滤器逻辑:在过滤器类中,可以实现以下方法来定义过滤器的逻辑: - OnActionExecuting:在执行控制器动作方法之前调用。 - OnActionExecuted:在执行控制器动作方法之后调用。 - OnResultExecuting:在执行结果之前调用。 - OnResultExecuted:在执行结果之后调用。 这些方法可以根据需要选择实现,以执行相应的逻辑。 3. 注册过滤器:可以通过在Startup.cs文件的`ConfigureServices`方法使用`services.AddMvc(options => options.Filters.Add<CustomFilter>())`来注册过滤器。也可以使用特性标记在控制器或动作方法上直接应用过滤器。 4. 应用过滤器过滤器可以应用于整个应用程序、控制器或单个动作方法。通过在Startup.cs文件的`Configure`方法使用`app.UseMvc()`来应用过滤器。 这样,当请求到达应用程序时,过滤器的逻辑会按照定义的顺序被执行,并可以在请求处理过程中插入自定义的逻辑。过滤器可以用于实现身份验证、日志记录、异常处理等功能。 需要注意的是,过滤器的执行顺序是按照注册的顺序来决定的,可以通过在注册过滤器时设置优先级来控制执行顺序。另外,过滤器还可以通过依赖注入来获取其他服务和组件,以便进行更复杂的逻辑处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值