【数据事务】.NET开源 ORM 框架 SqlSugar 系列

 .NET开源 ORM 框架 SqlSugar 系列

  1. 【开篇】.NET开源 ORM 框架 SqlSugar 系列
  2. 【入门必看】.NET开源 ORM 框架 SqlSugar 系列
  3. 【实体配置】.NET开源 ORM 框架 SqlSugar 系列
  4. 【Db First】.NET开源 ORM 框架 SqlSugar 系列
  5. 【Code First】.NET开源 ORM 框架 SqlSugar 系列
  6. 【数据事务】.NET开源 ORM 框架 SqlSugar 系列
  7. 【连接池】.NET开源 ORM 框架 SqlSugar 系列-CSDN博客

🔥数据库事务

数据库事务( transaction )是访问并可能操作各种 数据项 的一个数据库操作 序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。

🟢事务特性

  1. 原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
  2. 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。
  3. 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
  4. 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

1、单库事务 

单库事务是针 一个db 操作执行的事务,无论是 ISqlSugarClient 和  SqlSugarClient 用法都一样

try
    {
        db.Ado.BeginTran();

        db.Insertable(new Order() { .....}).ExecuteCommand();

        db.Insertable(new Order() { .....}).ExecuteCommand();

        db.Ado.CommitTran();

    }
    catch (Exception ex)
    {
        db.Ado.RollbackTran();
        throw ex;
    }

如果一个db就一个库,那么你也可以用多租户事务节约代码,因为2者在一个库的情况下作用一样。可以不写 .ado

db.BeginTran();//去掉了.ado

db.CommitTran();//去掉了.ado

db.RollbackTran();//去掉了.ado

//ISqlSugarClient 接口使用多租户事务 看文档2.2

2、多库事务(可跨库)

多数据库事务是SqlSugar独有的功能,稳定比 CAP 更强(CAP还有一层队列),在单个程序中可以很愉快的使用多库事务。

SqlSugarClient 或者 SqlSugarSope 继承于2个接口 ,代码如下事务:

SqlSugarClient : ISqlSugarClient, ITenant

多租户声明

SqlSugarClient db = new SqlSugarClient(new List<ConnectionConfig>()
{
  new ConnectionConfig()
  { ConfigId="0", DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection=true},
   
  new ConnectionConfig()
  { ConfigId="1", DbType=DbType.MySql,ConnectionString=..,IsAutoCloseConnection=true}
});

划重点:简单的说多租户事务和单库事务用法基本100%一致,唯一区别就是少了.Ado

2.1 SqlSugarClient 事务

因为继承  ITenant 了可以直接使用   (老版本var mysql=db.GetConnection要写在事务外面)

🚫注意:禁止使用 db.Ado.BeginTran ,多租户是 db.BeginTran

 //禁止使用 db.Ado.BeginTran,多租户是db.BeginTran
 try
 {
     db.BeginTran();
      
     db.GetConnection("1").Insertable(new Order() { }).ExecuteCommand();
     db.GetConnection("0").Insertable(new Order() { }).ExecuteCommand();
      
     db.CommitTran();
 }
 catch (Exception)
 {
     db.RollbackTran();//数据回滚
     throw;
 }
  
//主db
//注入的SqlSugarClient或者SqlSugarScope我们称为主db
  
//子db 
//通过租户方法GetConnection出来的我们称为子db,用来操作当前数据库,没有租户事务相关方法
  
//主db可以用事务管理多个子db ,也可以使用 GetConnection等租户方法
  
  
  
//目前底层是业务执行成功后统一提交事务,业务只要失败全部回滚,统一回滚过程中都有有3次重试回滚
//从目前用户使用情况来看,相当稳定几乎没有一例失败的反馈
//高安全级别数据:请使用差异日志+Catch(AggregateException ex)进行补偿机质
//如果回滚失败会throw new AggregateException

2.2 ISqlSugarClient 事务

 因为和ITenant没有继承关系,需要用 . AsTenAnt() 转换一下 。

db.AsTenant().BeginTran();//低版本 (db as ITenant).BeginTran() 

db.AsTenant().CommitTran();

db.AsTenant().RollbackTran();

3、调试事务

db.ContextId 要从事务开始,CURD 和事务结束 必须一致 这个事务才会生效,如果是MYSQL也检查一下表引擎是否支持事务。

❓不一致怎么办

  1. SqlsugarClient 可以用变量 var db=外部Db; 所有操作使用db保证一致。

  2. SqlsuagrScope (该对象是线程安全对象,可以单例)可以用单例模式保证一致。

image.png

测试代码 最好用 Insert ,因为 Update 有条件过滤等因素添会添加测试难度,我们用插入来进行测试会比较简单些

     try
      {
        db.BeginTran();

        Console.WriteLine(db.Queryable<Order>().Count());//插入前数量

        db.Insertable(new Order() { CreateTime=DateTime.Now, Name="aa",Price=1}).ExecuteCommand();

        Console.WriteLine(db.Queryable<Order>().Count());//插入后数量

        throw new Exception("出错");

        db.CommitTran();
      }
      catch
      {
        db.RollbackTran();

        Console.WriteLine(db.Queryable<Order>().Count());//回滚后数量
      }

输出结果 为 155 156 155  插入前和回滚后一样就说明成功的。

4、语法糖

语法糖1: 5.0.4才支持

这种适合有 全局异常 的,直接出错扔出错并且回滚。

  using (var tran = db.UseTran()){
 
        //业务代码
        //里面禁止写 try处理事务逻辑,格式一定按现在的风格来
 
        tran.CommitTran();
     }
     //要写 try处理异常可以写在外面

语法糖2:自动异常

这种适合 没有异常 处理的,减少了try 处理

   var result = db.UseTran(() =>
    {
        var beginCount = db.Queryable<Order>().ToList();

        db.Ado.ExecuteCommand("delete Order");

        var endCount = db.Queryable<Order>().Count();

        return true;// 返回值等行result.Data
    });

    if (result.Data==false//返回值为false
    {

            //result.Data 业务的返回值 

            //如果是上面的逻辑 result.Data==true肯定业务成功并且事务成功

            //if(result.IsSuccess==false)//事务执行了回滚

            //if(result.IsSuccess==true)//事务提交完成
    }

语法糖3:工作单元

UnitOfWork:  工作单元模式/IUnitOfWorK/DbContext - SqlSugar 5x - .NET果糖网

5、跨方法事务

SqlSugarScope 单例模式支持跨事务方法。

SqlSugarClient 需要 IOC 设置 Scoped 周期实现。

6、CAP事务 TCC 和 Saga

6.1 原理讲解

CAP可以支持跨程序间的事务处理(非跨程序事务不建议用,涉及到队列等,在单程序中稳定性肯定不如自带的多租户事务)

注意: MySql用户使用 升级到最新 

1、数据库的自动释放要关闭

2、手动打开数据库连接 db.Ado.Connection.Open();

3、用db.Ado.Connection创建事务

4、把你的事务赋值到ORM对象  db.Ado.Transaction = 你的事务;

5、执行你的代码

6、关闭Connection对象

//用户使用案例
var db=GetSqlsugarclient();
//关闭自动释放(需要 using手动释放)
db.CurrentConnectionConfig.IsAutoCloseConnection = false;
//取出ADO事务
using (var connection = (MySqlConnection)db.Ado.Connection)//SqlServer是SqlConnection
{
     using (var transaction = connection.BeginTransaction(_capBus, autoCommit: false))
     {
         if (connection.State != ConnectionState.Open)
         {
            connection.Open();
         }
 
          db.Ado.Transaction = (IDbTransaction)transaction.DbTransaction;//这行很重要
                  
          db.Insertable<Test>(new Test()
          {
            name = DateTime.Now.ToString()
          }).ExecuteCommand();
 
          _capBus.Publish("Sample.RabbitMQ.MySql", DateTime.Now);
 
         transaction.Commit();
 
       }
}

7、异步事务

📢 注意:请不要在同步方法里面写下面方代码,必须是异步方法才行 返回是要带有Task async 。

用法1:

  try
     {
          await db.BeginTranAsync(); 
 
              await db.Insertable(new Order()
              {
                    CreateTime = DateTime.Now,
                    CustomId = 1,
                    Name = "aaa",
                    Price = 0
               }).ExecuteCommandAsync();
 
          await db.CommitTranAsync();
       }
       catch (Exception)
       {
          await  db.RollbackTranAsync();
        }

用法2:

  //只有5.0.3.8支持,老版本请升级使用
  var res = await db.UseTranAsync(async () =>
  {
      await db.Insertable(new Order()
      {
          CreateTime = DateTime.Now,

          CustomId = 1,

          Name = "aaa",

          Price = 0

       }).ExecuteCommandAsync();
        
       return true;//返回值会变成 res.Data

   });

    if (result.Data==false//返回值为false
    {  

        //result.Data 业务的返回值

        //如果是上面的逻辑 result.Data==true肯定业务成功并且事务成功

        //if(result.IsSuccess==false)//事务执行了回滚

        //if(result.IsSuccess==true)//事务提交完成

    }

   //注意:

   //await db.UseTranAsync 前面的await不要漏掉了

8、设置事务隔离级别

单库模式用法:

try
{
    db.Ado.BeginTran(IsolationLevel.ReadCommitted);
         
        //业务代码  
         
    db.Ado.CommitTran();
}
catch (Exception ex)
{
    db.RollbackTran();
    throw ex;
}

多租户模式:

 var mysqlDb = db.GetConnection("mysql");
 var mssqlDb = db.GetConnection("mssql");
 try
 {
        mysqlDb.Ado.BeginTran(IsolationLevel.ReadCommitted);//开启库1的事务
        mssqlDb.Ado.BeginTran(IsolationLevel.ReadCommitted);//开启库2的事务

        //业务代码 只能用  mysqlDb和 mssqlDb 

        db.CommitTran();//注意不能用db.ado.CommitTran

 }
 catch (Exception ex)
 {
        db.RollbackTran();

        throw ex;
}

9、嵌套事务(支持异步)

 9.1. 共享模式 

有外部事务,内部事务用外部事务(推荐)

通过 工作单元 实现嵌套事务  5.1.2.5-preview03

 //db.Ado.IsNoTran()表示事务为null才开启事务

    using (var uow = db.CreateContext(db.Ado.IsNoTran())) 
    {
         using (var uow2 = db.CreateContext(db.Ado.IsNoTran()))
         { 
            uow2.Commit();
         }

       uow.Commit(); //禁止用 db.RollBack 工作单元内只要throw会自动回滚
     }

 9.2. 子事务独立 (不推荐)

🚫不推荐原因:这种很容易出现坑,比如业务A和业务B都用到了一样的表就会死锁

事务嵌套:推荐用9.1或者标题10 ,9.2是不推荐的

 try
 {
     db.BeginTran();
     //业务..A
      
      var childDb=db.CopyNew();
      try
      {
 
         childDb.BeginTran();
         //...业务B
         childDb.Commit();
       }
       catch (Exception)
       {
          childDb.RollbackTran();//数据回滚
          throw;
       }
      
     db.CommitTran();
 }
 catch (Exception)
 {
     db.RollbackTran();//数据回滚
     throw;
 }

10、工作单元【事务特性】

在 .NET Core 中,可以使用自定义的 ActionFilter 来封装事务。

 [ServiceFilter(typeof(TransactionFilter))]//加上这行就可以用了
 public IEnumerable<WeatherForecast> Get()
 {
        .....数据库操作...     
 }

10.1 创建全局事务

  public class TransactionFilter : IActionFilter
   {
          
        ISqlSugarClient _db;//你也可以换EF CORE对象 或者ADO对象都行
        public TransactionFilter(ISqlSugarClient db)//(ISqlSugarClient)需要IOC注入处理事务的对象
        { 
            _db=db;
        }
 
        public void OnActionExecuting(ActionExecutingContext context)
        {
             _db.AsTenant().BeginTran();//接口要加.AsTenant()
        }
 
        public void OnActionExecuted(ActionExecutedContext context)
        {
            if (context.Exception == null)
            {
                _db.AsTenant().CommitTran();
            }
            else
            {
                _db.AsTenant().RollBack();
            }
        }
    }

10.2 IOC注册

//注入事务对象
builder.Services.AddScoped<TransactionFilter>();
 
//注入ORM对象
//注册上下文:AOP里面可以获取IOC对象,如果有现成框架比如Furion可以不写这一行
services.AddHttpContextAccessor();
//注册SqlSugar
services.AddSingleton<ISqlSugarClient>(s =>
{
    SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
    {
        DbType = SqlSugar.DbType.Sqlite,
        ConnectionString = "DataSource=sqlsugar-dev.db",
        IsAutoCloseConnection = true,
    },
   db =>
   {
       //单例参数配置,所有上下文生效
       db.Aop.OnLogExecuting = (sql, pars) =>
       {
           //获取作IOC作用域对象
           //var appServive = s.GetService<IHttpContextAccessor>();
           //var obj = appServive?.HttpContext?.RequestServices.GetService<Log>();
           //Console.WriteLine("AOP" + obj.GetHashCode());
       };
   });
    return sqlSugar;
});

10.3 在接口打上事务 

 [ServiceFilter(typeof(TransactionFilter))]//加上这行就可以用了
 [HttpGet(Name = "GetWeatherForecast")]
 public IEnumerable<WeatherForecast> Get()
 {
        .....数据库操作...     
 }

11、MySql注意事项 

(1)MYSQL不支持创建表和删除表处理事务,原生事务也一样 。

(2)MyISAM 存储引擎不支持事务 需要改成 InnoDB

image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/927759.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

南昌大学(NCU)羽毛球场地预约脚本

在冬天进行羽毛球运动是一个很好的选择&#xff0c;它能帮助你保持身体活力&#xff0c;增强心肺功能&#xff0c;并促进血液循环。但是室友和师弟师妹反应&#xff0c;学校的羽毛球场地有限&#xff0c;手速慢的根本预约不到场地。 中午12&#xff1a;00准时开放预约&#xff…

三种方式(oss、本地、minio)图片的上传下载

一、OSS 1、前期准备 1.1 注册阿里云账号&#xff0c;开启对象存储oss功能&#xff0c;创建一个bucket&#xff08;百度教程多的是&#xff0c;跟着创建一个就行&#xff0c;创建时注意存储类型是标准存储&#xff0c;读写权限是公共读&#xff09; 有的在创建桶时读写属性是…

关于Nginx前后端分离部署spring boot和vue工程以及反向代理的配置说明

最近项目中用到关于Nginx前后端分离部署spring boot和vue工程以及反向代理的配置&#xff0c;总结了一下说明&#xff1a; 1、后端是spring boot工程&#xff0c;端口8000&#xff0c;通过 jar命令启动 nohup java -jar xxx-jsonflow-biz.jar > /usr/local/nohup.out 2>…

debian 11 虚拟机环境搭建过坑记录

目录 安装过程系统配置修改 sudoers 文件网络配置换源安装桌面mount nfs 挂载安装复制功能tab 无法补全其他安装 软件配置eclipse 配置git 配置老虚拟机硬盘挂载 参考 原来去 debian 官网下载了一个最新的 debian 12&#xff0c;安装后出现包依赖问题&#xff0c;搞了半天&…

Android:生成Excel表格并保存到本地

提醒 本文实例是使用Kotlin进行开发演示的。 一、技术方案 org.apache.poi:poiorg.apache.poi:poi-ooxml 二、添加依赖 [versions]poi "5.2.3" log4j "2.24.2"[libraries]#https://mvnrepository.com/artifact/org.apache.poi/poi apache-poi { module…

RK3576技术笔记之一 RK3576单板介绍

第二篇嘛&#xff0c;亮亮我们做出来的板子&#xff0c;3576这个片子的基本功能接口单板都做了&#xff0c;接口数量肯定是比不上3588&#xff08;PS&#xff1a;这个我们也在做&#xff0c;后续都完成后会发文章&#xff09;&#xff0c;但是比起3568来说还是升级了&#xff0…

SQL进阶技巧:如何寻找同一批用户 | 断点分组应用【最新面试题】

目录 0 问题描述 1 数据准备 2 问题分析 ​编辑 3 小结 0 问题描述 用户登录时间不超过10分钟的视为同一批用户,找出以下用户哪些属于同一批用户(SQL实现) 例如: user_name time a 2024-10-01 09:55 b 2024-10-01 09:57 c 2024-10-01…

数字图像处理(11):RGB转YUV

&#xff08;1&#xff09;RGB颜色空间 RGB颜色空间&#xff0c;是一种基于红色、绿色、蓝色三种基本颜色进行混合的颜色空间&#xff0c;通过这三种颜色的叠加&#xff0c;可以产生丰富而广泛的颜色。RGB颜色空间在计算机图像处理、显示器显示、摄影和影视制作等领域具有广泛应…

利用Ubuntu批量下载modis图像(New)

由于最近modis原来批量下载的代码不再直接给出&#xff0c;因此&#xff0c;再次梳理如何利用Ubuntu下载modis数据。 之前的下载代码为十分长&#xff0c;现在只给出一部分&#xff0c;需要自己再补充另一部分。之前的为&#xff1a; 感谢郭师兄的指导&#xff08;https://blo…

HTTP 长连接(HTTP Persistent Connection)简介

HTTP长连接怎么看&#xff1f; HTTP 长连接&#xff08;HTTP Persistent Connection&#xff09;简介 HTTP 长连接&#xff08;Persistent Connection&#xff09;是 HTTP/1.1 的一个重要特性&#xff0c;它允许在一个 TCP 连接上发送多个 HTTP 请求和响应&#xff0c;而无需为…

淘宝商品详情主图SKU图价格|品牌监控|电商API接口

淘宝/天猫获得淘宝商品详情 API 返回值说明 item_get-获得淘宝商品详情 taobao.item_get 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&a…

单片机学习笔记 17. 串口通信-发送汉字

更多单片机学习笔记&#xff1a;单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…

五层网络协议(封装和分用)

目录 七层网络协议五层网络协议封装1.应用层2.传输层3.网络层4.数据链路层5.物理层 分用1. 物理层2.数据链路层3.网络层 IP 协议4.传输层 UDP 协议5.应用层 七层网络协议 网络通信过程中&#xff0c;需要涉及到的细节&#xff0c;其实是非常非常多的&#xff0c;如果要有一个协…

阿里云人工智能平台(PAI)免费使用教程

文章目录 注册新建实例交互式建模(DSW)注册 注册阿里云账号进行支付宝验证 新建实例 选择资源信息和环境信息,填写实例名称 资源类型需要选择公共资源,才能使用资源包进行抵扣。目前每月送250计算时。1 * NVIDIA A10 8 vCPU 30 GiB 1 * 24 GiB1 * NVIDIA V100 8 vCPU 32 Gi…

【实战】Oracle基础之控制文件内容的5种查询方法

关于Jady&#xff1a; ★工作经验&#xff1a;近20年IT技术服务经验&#xff0c;熟悉业务又深耕技术&#xff0c;为业务加持左能进行IT技术规划&#xff0c;右能处理综合性故障与疑难杂症&#xff1b; ★成长历程&#xff1a;网络运维、主机/存储运维、程序/数据库开发、大数…

蓝桥杯第 23 场 小白入门赛

一、前言 好久没打蓝桥杯官网上的比赛了&#xff0c;回来感受一下&#xff0c;这难度区分度还是挺大的 二、题目总览 三、具体题目 3.1 1. 三体时间【算法赛】 思路 额...签到题 我的代码 // Problem: 1. 三体时间【算法赛】 // Contest: Lanqiao - 第 23 场 小白入门赛 …

使用 Pytorch 构建 Vanilla GAN

文章目录 一、说明二、什么是 GAN&#xff1f;三、使用 PyTorch 的简单 GAN&#xff08;完整解释的代码示例&#xff09;3.1 配置变量3.2 、PyTorch 加速3.3 构建生成器3.4 构建鉴别器 四、准备数据集五、初始化函数六、前向和后向传递七、执行训练步骤八、结果 一、说明 使用…

【Windows 11专业版】使用问题集合

博文将不断学习补充 I、设置WIN R打开应用默认使用管理员启动 1、WIN R输入 secpol.msc 进入“本地安全策略”。 2、按照如下路径&#xff0c;找到条目&#xff1a; “安全设置”—“本地策略”—“安全选项”—“用户账户控制&#xff1a;以管理员批准模式运行所有管理员” …

合规性要求对漏洞管理策略的影响

讨论漏洞管理中持续面临的挑战&#xff0c;包括确定漏洞的优先级和解决修补延迟问题。 介绍合规性要求以及自动化如何简化漏洞管理流程。 您认为为什么尽管技术不断进步&#xff0c;但优先考虑漏洞和修补延迟等挑战仍然存在&#xff1f; 企业基础设施日益复杂&#xff0c;攻…

IDEA全局设置-解决maven加载过慢的问题

一、IDEA全局设置 注意&#xff1a;如果不是全局设置&#xff0c;仅仅针对某个项目有效&#xff1b;例在利用网上教程解决maven加载过慢的问题时&#xff0c;按步骤设置却得不到解决&#xff0c;原因就是没有在全局设置。 1.如何进行全局设置 a.在项目页面&#xff0c;点击f…