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

news2025/1/15 21:00:02

 .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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【381】基于springboot的银行客户管理系统

摘 要 伴随着信息技术与互联网技术的不断发展&#xff0c;人们进到了一个新的信息化时代&#xff0c;传统管理技术性没法高效率、容易地管理信息内容。为了实现时代的发展必须&#xff0c;提升管理高效率&#xff0c;各种各样管理管理体系应时而生&#xff0c;各个领域陆续进到…

VUE前端实现天爱滑块验证码--详细教程

第一步&#xff1a; Git地址&#xff1a;tianai-captcha-demo: 滑块验证码demo 找到目录 src/main/resources/static,拷贝 static 并改名为 tac 即可。 第二步&#xff1a; 将改为 tac 的文件&#xff0c;放进项目根目录中&#xff0c;如下图&#xff1a; 第三步&#xff1…

Profinet转EtherNet/IP网关是如何解决西门子S7-1500PLC与AB PLC的通讯问题的

一、 案例背景 在一个工业现场&#xff0c;一端是AB的PLC&#xff0c;IP地址192.168.1.20;另一端西门子是S7-1500系列&#xff0c;IP地址192.168.2.248。AB的PLC内有 B3、N7、F8 三个寄存器文件涉及到通讯&#xff0c;分别对应西门子PLC的M、DB1、DB2三个存储区域。通过捷米特…

SpringCloud Seata集成分布式事务管理 事务保护 XA AT两种模式的区别

介绍 阿里巴巴的 Seata&#xff08;Service Aligned Transaction Alternative&#xff09;是一个开源的分布式事务解决方案&#xff0c;旨在解决微服务架构中跨服务、跨数据库的事务一致性问题。它可以帮助开发者管理分布式系统中的全局事务&#xff0c;确保在多个服务之间的事…

java全栈day10--后端Web基础(基础知识)之续集

一、Servlet执行流程 二、Http协议&#xff08;相对Tomcat和servlet重要一点&#xff09; 2.1Http-概叙 2.2Http-请求协议 2.2.3请求数据格式 2.2.3请求数据获取 先启动服务器 访问/hello Servlet 访问浏览器端Http协议数据 查看数据 如何获取具体说明&#xff1a; 代码演示 …

【Python】ASCII-generator 将图像、文本或视频转换为 ASCII 艺术 生成字符图(测试代码)

目录 预览效果安装环境报错分析基本例程总结 欢迎关注 『Python』 系列&#xff0c;持续更新中 欢迎关注 『Python』 系列&#xff0c;持续更新中 预览效果 原图 黑白图 彩色图 安装环境 拉取代码 https://github.com/vietnh1009/ASCII-generatorpython3.8 pip install…

2024年大热,Access平替升级方案,也适合Excel用户

欢迎各位看官&#xff0c;您来了&#xff0c;就对了&#xff01; 您多半是Access忠实粉丝&#xff0c;至少是excel用户&#xff0c;亦或是WPS用户吧。那就对了&#xff0c;今天的分享肯定对您有用。 本文1100字&#xff0c;阅读时长2分50秒&#xff01; 现实总是不尽人意&am…

SpringMVC:入门案例

从此开始&#xff0c;我们步入SpringMVC的学习。 SpringMVC是一种基于Java实现MVC模型的轻量级Web框架 先来看一下web程序是如何工作的&#xff1a; 因为是异步调用&#xff0c;所以后端不需要返回view视图&#xff0c;将其去除前端如果通过异步调用的方式进行交互&#xff0…

云计算实验室建设方案

一、云计算实验室建设方案 云计算实验教学整体解决方案&#xff0c;包括&#xff1a;云计算服务器集群、云计算实训平台、实训课程体系、行业实战课程系统、行业数据等&#xff0c;系统性地解决云计算实训教学的痛点问题。 【硬件系统】云计算实训一体机 云计算实训一体机是唯…

QT基础学习day1

一&#xff0c;QT介绍 1.1&#xff0c;什么是 Qt Qt 是一个跨平台的 C\python图形用户界面应用程序框架。 它为应用程序开发者提供建立艺术级图形界面所需的所有功能。 它是完全面向对象的&#xff0c;很容易扩展&#xff0c;并且允许真正的组件编程。 1.1 &#xff0c;Py…

LabVIEW内燃机气道试验台测控系统

基于LabVIEW软件开发的内燃机气道试验台测控系统主要应用于内燃机气道的性能测试和数据分析&#xff0c;通过高精度的测控技术&#xff0c;有效提升内燃机的测试精度和数据处理能力。 项目背景 随着内燃机技术的发展&#xff0c;对其气道性能的精准测量需求日益增加。该系统通…

MAUI APP开发蓝牙协议的经验分享:与跳绳设备对接

在开发MAUI应用程序时&#xff0c;蓝牙协议的应用是一个重要的环节&#xff0c;尤其是在需要与外部设备如智能跳绳进行数据交换的场景中。以下是我在开发过程中的一些经验和心得&#xff0c;希望能为你的项目提供帮助。 1. 蓝牙协议基础 蓝牙协议是无线通信的一种标准&#x…

centos7调用so库无响应

这里使用centos7部署一个springboot项目调用so库函数时&#xff0c;无任何响应与输出、也无任何报错信息。以下是我使用的服务器信息&#xff1a; 解决方法&#xff1a; 这里我先直接说下解决方法。有效的解决方法是将你的 so 库文件上传至服务器的 lib 目录中&#xff0c;并对…

使用 PDF API 合并 PDF 文件

内容来源&#xff1a; 如何在 Mac 上合并 PDF 文件 1. 注册与认证 您可以注册一个免费的 ComPDFKit API 帐户&#xff0c;该帐户允许您在 30 天内免费无限制地处理 1,000 多个文档。 ComPDFKit API 使用 JSON Web Tokens 方法进行安全身份验证。从控制面板获取您的公钥和密钥&…

多线程相关案例

目录 1. 单例模式 1) 饿汉模式 2) 懒汉模式 2. 阻塞队列 1) 阻塞队列的特性 2) 模拟实现阻塞队列 3. 定时器 4. 线程池 1) ThreadPoolExecutor 类 2) 模拟实现线程池 1. 单例模式 单例模式是最经典的设计模式之一。 单例模式&#xff0c;顾名思义&#xff0c;就是这…

【PyQt入门】麦当劳会员登录页面实战

PyQt思维导图&#xff1a; 效果图如下&#xff1a; 设计页面包含&#xff1a;图标&#xff08;含动图gif&#xff09;&#xff0c;窗口logo&#xff0c;title&#xff0c;文本框&#xff0c;按钮 素材图如下&#xff1a; 完整代码以及标注如下&#xff1a; # 导入必要的PyQt6…

中断,定时器相关内容

中断&#xff0c;定时器相关内容 单片机中断什么是单片机的中断中断嵌套中断的优点中断结构中断相关寄存器中断优先级IP中断号中断响应条件中断使用实例在这里插入代码片 定时器CPU 时序的有关知识定时器原理定时计数结构定时/计数器的寄存器定时器配置功能实现 单片机中断 高位…

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

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

在鲲鹏麒麟服务器上部署MySQL主从集群

因项目需求需要部署主从MySQL集群&#xff0c;继续采用上次的部署的MySQL镜像arm64v8/mysql:latest&#xff0c;版本信息为v8.1.0。计划部署服务器192.168.31.100和192.168.31.101 部署MySQL主节点 在192.168.31.100上先创建好/data/docker/mysql/data和/data/docker/mysql/l…

一款支持80+语言,包括:拉丁文、中文、阿拉伯文、梵文等开源OCR库

大家好&#xff0c;今天给大家分享一个基于PyTorch的OCR库EasyOCR&#xff0c;它允许开发者通过简单的API调用来读取图片中的文本&#xff0c;无需复杂的模型训练过程。 项目介绍 EasyOCR 是一个基于Python的开源项目&#xff0c;它提供了一个简单易用的光学字符识别&#xff…