首页 > 数据库 >simpread-课程 24:工作单元之数据库事务【AOP】

simpread-课程 24:工作单元之数据库事务【AOP】

时间:2024-04-30 16:56:45浏览次数:18  
标签:24 事务 代码 UnitOfWorkAttribute 添加 context AOP Action simpread

一、工作单元事务代码分析

在上一个课程,我们已经实现了数据库事务功能,来保证数据的完整性。

通过上一个课程的实现方式,我们在每一个 Action 开头和结尾,都需要添加对应的代码,才能实现事务功能,具体见以下截图:

这种实现方式存在以下 2 个问题:

  1. 在具体业务开发中,一个请求往往都会涉及多次数据库操作,所有 Action 都必须添加对应的事务代码;

  2. 虽然实现事务代码比较简单,但是代码是比较重复的,这样就会导致所有 Action 充斥着重复的代码。

二、工作单元事务重构

根据上面的分析,为了消除重复的代码,我们可以通过自定义 WebApi 的行为过滤器,来实现在 Action 执行前与执行后,添加事务开启与提交的代码。

2.1 添加行为过滤器

在 Electric.API 项目,创建文件夹 UOW,并新增 UnitOfWorkFilterAttribute 类。

UnitOfWorkFilterAttribute 完整代码如下:

using Electric.Repository.UOW;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Electric.API.UOW
{
    public class UnitOfWorkFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var _unitOfWork = context.HttpContext.RequestServices.GetService(typeof(IUnitOfWork)) as UnitOfWork;
            _unitOfWork.BeginTransaction();
        }

        public override void OnActionExecuted(ActionExecutedContext context)
        {
            var _unitOfWork = context.HttpContext.RequestServices.GetService(typeof(IUnitOfWork)) as UnitOfWork;
            _unitOfWork.Commit();
        }
    }
}

代码说明:

  1. 继承行为过滤器 ActionFilterAttribute;
  2. 实现 OnActionExecuting 方法:开启事务,此方法会在 action 方法运行之前调用;
  3. 实现 OnActionExecuted 方法:提交事务,此方法会在 action 方法运行之后调用。

2.2 事务行为过滤器使用方法

我们可以通过为每一个 Action 添加 [UnitOfWorkFilter],来实现事务功能。使用方式见以下截图:

通过自定义过滤器,可以大大简化我们的代码,我们只需为需要事务的 Action,添加特性注解就可以。

2.3 全局添加事务行为过滤器

通过为每一个 Action 添加 [UnitOfWorkFilter],可以简化我们的代码,但是我们还可以进一步简化。
WebAPI 在添加控制器服务方法里,我们可以添加 Action 的配置,从而自定义 Action 的行为。

在 MVCExtension 添加全局的工作单元过滤器。

对应的 Action 的特性,也都没必要添加,可以移除。

全局注册的优缺点:

优点:

  1. 开发人员无需关心事务的实现,只需专心业务代码的开发;

  2. 所有的 Action 默认添加事务,避免需要事务功能的 Action 遗漏。

缺点:

  1. 增加事务开销,很多 Action 只有查询命令,没必要使用事务;

  2. 存在大事务的问题,Action 里面的查询命令无需事务,但是事务特性是在 Action 执行前开启的,导致所有 Select 也会开启事务。

全局注入事务,可以大大简化我们的代码,但也存在一些缺点。所以,我们可以通过为 Action 添加特性,来实现事务的开关功能,为没必要事务的 Aciton,移除事务功能。

三、工作单元事务开关

3.1 添加事务开关

在 Electric.API 项目,新增 UnitOfWorkAttribute 类。

UnitOfWorkAttribute 完整代码如下:

namespace Electric.API.UOW;

public class UnitOfWorkAttribute : Attribute
{
    public bool IsTransactional { get; set; } = true;
}

代码说明:

1、UnitOfWorkAttribute 继承 Attribute;

2、属性 IsTransactional,用来配置是否开启事务,默认值为 true,默认开启。

3.2 修改事务过滤器特性

在事务过滤器特性,我们要通过获取 Action 的特性,来判断是否需要开启事务。

以下截图,代码实现功能:通过获取 Action 的 UnitOfWorkAttribute,来判断是否需要开启事务。

UnitOfWorkFilterAttribute 修改后的完整代码:

using Electric.Repository.UOW;

using Microsoft.AspNetCore.Mvc.Filters;

namespace Electric.API.UOW;


public class UnitOfWorkFilterAttribute : ActionFilterAttribute
{

    private UnitOfWorkAttribute? _unitOfWorkAttribute;

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        _unitOfWorkAttribute = context.ActionDescriptor.EndpointMetadata.FirstOrDefault(x => x.GetType() == typeof(UnitOfWorkAttribute)) as UnitOfWorkAttribute;

        if (_unitOfWorkAttribute != null && !_unitOfWorkAttribute.IsTransactional)
        {
            return;
        }

        var _unitOfWork = context.HttpContext.RequestServices.GetService(typeof(IUnitOfWork)) as UnitOfWork;
        _unitOfWork.BeginTransaction();
    }
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        if (_unitOfWorkAttribute != null && !_unitOfWorkAttribute.IsTransactional)
        {
            return;
        }
        var _unitOfWork = context.HttpContext.RequestServices.GetService(typeof(IUnitOfWork)) as UnitOfWork;
        _unitOfWork.Commit();
    }
}

代码说明:

1、OnActionExecuting:action 执行之前,判断是否需要开启事务;

2、OnActionExecuted:action 执行之后,判断是否需要提交事务。

3.3 关闭事务

我们可以为所有的 Get 请求,关闭事务,使用方法如下:

关闭用户搜索事务:

关闭获取角色的权限列表事务:

可以为所有 Controller 的所有 Get 请求,关闭事务。

当然了,如果 Put、Post、Patch 的方法里,如果只是单个数据库操作的,也是可以关闭事务的,使用 SaveChanges 默认事务就可以。

对于一般的管理系统,并发性都比较低的,一般默认开启事务就可以,针对个别事务开销比较大的 Action,个性化开发就可以。

标签:24,事务,代码,UnitOfWorkAttribute,添加,context,AOP,Action,simpread
From: https://www.cnblogs.com/zhuoss/p/18168326

相关文章

  • P10242 [THUSC 2021] Emiya 家明天的饭
    题目大意有\(n\)个人和\(m\)种菜,第\(i\)个人对第\(j\)道菜的喜爱程度为\(a_{i,j}\)。如果\(a_{i,j}=-1\)则表示不喜欢。现在你要选择一个菜的集合,你会获得喜欢集合中所有菜的人对这些菜的喜爱程度之和的权值,最大化这个权值,\(n\leq20,m\leq10^6,a_{i,j}\leq10......
  • P10241 [THUSC 2021] 白兰地厅的西瓜
    考虑DP,注意到一个简单路径可以被拆为向上的部分和向下的部分。所以设\(f_{u,i}\)表示\(u\)的子树中从\(u\)向下且第一项是\(i\)的LIS的最大长度,\(g_{u,i}\)表示\(u\)的子树中\(u\)的某个子孙向上到\(u\)且最后一项是\(i\)的LIS的最大长度。从\(u\)到父......
  • 解锁HDC 2024之旅:从购票到报名,全程攻略
    本文分享自华为云社区《解锁HDC2024之旅:从购票到报名,全程攻略》,作者:华为云社区精选。Hi,代码界的小伙伴们,集结号已经吹响了!华为开发者大会(HDC2024)——这场汇聚了HarmonyOSNEXT鸿蒙星河版、盘古大模型5.0等创新火花与智慧碰撞的盛宴,将于6月21日至23日在东莞松山湖盛大开启。你是......
  • 24.什么是跨域?解决方案有哪些?
    为什么会出现跨域问题存在浏览器同源策略,所以才会有跨域问题。那么浏览器是出于何种原因会有跨域的限制呢。其实不难想到,跨域限制主要的目的就是为了用户的上网安全。同源策略导致的跨域是浏览器单方面拒绝响应数据,服务器端是处理完毕并做出了响应的。什么是同源策略一个url由......
  • simpread-课程 21:API 项目重构
    项目结构重构1.1Electric.DbMigrator存在的问题我们先来看下,后台API项目的目录结构。其中Electric.DbMigrator,这个项目作用是用来做数据库迁移的,但是同时也会被其他项目引用,还有这个项目类型还是WebAPI类型的。所以存在以下的几个问题:1、项目功能重合:数据库迁移和数......
  • 2024 开源数据工程生态系统全景图
    2024开源数据工程生态系统全景图(转)简介​ 虽然生成式人工智能和ChatGPT带来的沸沸扬扬的炒作令科技界为之一振,但在数据工程领域,2023年仍然是一个令人振奋和充满活力的一年,数据工程生态系统变得更加多样化和复杂化,系统中的所有层面都在不断创新和演进。​ 随着各种开源工具、......
  • 【2024-04-29】最后的稻草
    20:00我们要使错误小一些,这是可能的。但否认我们会有错误,那是不现实的,那就不是世界,不是地球,而是火星了。                                                 ——MXX刚......
  • 云原生周刊:K8s 中的服务和网络 | 2024.4.29
    开源项目推荐k8s-image-swapperk8s-image-swapper是Kubernetes的一个变更Webhook,它将镜像下载到自己的镜像仓库,并将镜像指向该新位置。它是dockerpull-throughproxy的一个替代方案。KubeIPv2KubeIPv2是DoiTKubeIPv1-main开源项目的全面改进版本,最初由AvivLau......
  • 2024.4.29鲜花/校庆
    正文若干年后,星际旅行和永生技术已经成为现实,\(214\)岁的我在一颗名为XY星的星球上成为了星际新闻局局长。记得那天是幻想历元年四月二十九日,我在审核今天的新闻稿时发现了这样一篇报道:XMSY中学即将迎来\(110\)周年校庆...一个破学校的校庆能出现在星际新闻上,很奇怪吧......
  • 2024年,提升Windows开发和使用体验实践 - 小工具篇
    前言#本来是一篇文章的,不知不觉写成了系列。其实开工那几天就已经写好了长文,这几天一忙就没连着发了。本文介绍一些Windows上用的小工具。美化/折腾/小工具#虽然这是在用Windows,但阻止不了我想折腾的心!把玩Linux的那些花样拿出来,虽然Windows可以自定义的程度没有Li......