【并发控制、更新、版本控制】.NET开源ORM框架 SqlSugar 系列

news2025/2/13 8:49:40

系列文章目录

🎀🎀🎀 .NET开源 ORM 框架 SqlSugar 系列 🎀🎀🎀


文章目录

  • 系列文章目录
  • 一、并发累计(累加)
    • 1.1 单条批量累计+
    • 1.2 批量更新并且字段+1
    • 1.3 批量更新并且字段+list中对应的值
  • 二、防止提交覆盖,重复提交(乐观锁)
    • 2.1 不依赖库同步 (新功能)
    • 2.2 依赖库同步(老功能)
    • 2.3 一对多提交
  • 三、悲观锁的用法
    • 3.1 悲观锁等待模式
    • 3.2 悲观锁排它模式
    • 在这里插入图片描述
  • 🎀🎀🎀 .NET开源 ORM 框架 SqlSugar 系列 🎀🎀🎀


一、并发累计(累加)

1.1 单条批量累计+

比如要扣钱什么的,或者数字叠加,这种就需要通过 set 字段=段字段+1 这种方处理。

//正确写法:安全的字段累计
var result= db.Updateable<Student>().SetColumns(it => it.Num== it.Num+1).Where(it => it.Id == 1).ExecuteCommand();
//sql: num=num+1 
 
 
//错误写法: 在程序中计算是不安全的
var num=data.num+1
var result= db.Updateable<Student>().SetColumns(it => it.Num== num).Where(it => it.Id == 1).ExecuteCommand();
//sql:  num=值

🎯注意:这种更新方式只适合明确主键的更新,条件形态的建议用下面的锁。

1.2 批量更新并且字段+1

 var result67 =
          db.Updateable(updateObjs)
          //批量更新单独处理num列 set num=num+1
          .PublicSetColumns(it => it.Num, it => it.Num+ 1)
          .ExecuteCommand();

1.3 批量更新并且字段+list中对应的值

   db.Updateable(list)
   PublicSetColumns(it => it.Price, "+") //set price=price+list[i].price
   .ExecuteCommand();

二、防止提交覆盖,重复提交(乐观锁)

📌使用乐观锁需要满足2个条件:

  1. 用户要打开编辑界面,然将数据绑定到编辑界面
  2. 用户在界面填写完在点修改保存

💯原理: 打开编辑框太久别人已经修改了这条记录,我在提交就可能把别人更新数据清空掉,我们需要一个时间字段去和数据库中的Version比对

🎇重现步骤:开2个浏览器 ,编辑同一条记录, A浏览器先保存,然后B浏览器在保存就能重现

因为是同一条记录本身并不存在并发,因为编辑界面打开一天也不会刷新数据,点保存一样覆盖

2.1 不依赖库同步 (新功能)

新项目推荐用新功能,使用方便有问题及时沟通

    public class ULockEntity
    {
        [SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int Id { get; set; }
        public string Name { get; set; }
        [SqlSugar.SugarColumn(IsEnableUpdateVersionValidation = true)]//标识版本字段
        public long Ver { get; set; } 
         
        //支持Guid long string DateTime (不推荐DateTime 时间有精度问题)
        //推荐用 string guid  (使用long要序列化成strting不然前端精度丢失)
    }
     
    //注意:只能是实体更新不能是集合更新
     
    //【用法1:不扔错】 Ver与数据库字段不同不报错返回0
    var rows = db.Updateable(new ULockEntity()
    {
        Id = id,
        Name = "newname",
        Ver = 1551128313597136896//版本字段会自动更新
    }).ExecuteCommandWithOptLock(); 
     
     
    //【用法2:扔出错误】Ver与数据库字段不同直接扔错出误
    var rows = db.Updateable(new ULockEntity()
    {
        Id = id,
        Name = "newname",
        Ver = 1551128313597136896  //版本字段会自动更新
    }).ExecuteCommandWithOptLock(true); //加上true就会扔出错误
    //try { ... }catch(VersionExceptions ex){...}
    //底层 throw new VersionExceptions
    
    /*********完整测试用例*********/
     
    //添加测试数据
    var db = NewUnitTest.Db;
    db.CodeFirst.InitTables<ULockEntity>();
    db.DbMaintenance.TruncateTable<ULockEntity>();
    //第一次插入ver=0
    var id = db.Insertable(new ULockEntity(){Name = "oldName" ,Ver=0}).ExecuteReturnIdentity();
     
    //开始用例
    var rows= db.Updateable(new ULockEntity()
    {
        Id = id,
        Name = "newname",
        Ver = 0  //会自动更新版本字段更新后数据库将不在是0
    }).ExecuteCommandWithOptLock();  
    //rows=1 因为数据库ver是0你传的也是0
 
    var rows= db.Updateable(new ULockEntity()
    {
        Id = id,
        Name = "newname2",
        Ver = 0
    }).ExecuteCommandWithOptLock();   
    //rows=0  失败:数据库ver不等于0

2.2 依赖库同步(老功能)

例如:SqlServer 中的时间戳类型的字段,会在这条记录变更后会自动更新,如果没这种机质的字段你也可以用触发器实现这种机质

有这种机质我们只要打个特性就能实现并发控制,代码如下:

数据库数据库实体
SQLSERVERtimestamp默认自动更新)byte[]
其他数据库timestamp(需要配置自动更新)DateTime

public class StudentVersion    
{
  [SugarColumn(IsPrimaryKey =true,IsIdentity =true)]    
 public int Id { get; set; }    
 public string Name { get; set; }    
 public DateTime CreateTime { get; set; }    
 [SqlSugar.SugarColumn(
             IsEnableUpdateVersionValidation = true,//标识版本字段 
             IsOnlyIgnoreInsert=true,//禁止插入
             IsOnlyIgnoreUpdate=true,//禁止更新
             ColumnDataType="timestamp" //时间戳类型,有些库需要配置或者有差异
              )]   
  
 // SqServer byte[] 其它数据库用 DateTime                        
 public byte[]  Timestamp { get; set; } 
}    
db.Updateable(data).IsEnableUpdateVersionValidation().ExecuteCommand();//更新的时候启用验证

原理:

 //查询这条记录
 var data = db.Queryable<StudentVersion>().InSingle(id);
  
 //成功 (data.Timestamp等于数据库中的 Timestamp字段)
 db.Updateable(data).IsEnableUpdateVersionValidation().ExecuteCommand();//执行后数据库Timestamp更新
  
 //失败 (data.Timestamp不等于数据库中的 Timestamp字段)
 db.Updateable(data).IsEnableUpdateVersionValidation().ExecuteCommand();

如何知道是并发错误,还是其他错误

//底层代码 
throw new VersionExceptions //捕获异常的时候只要是 VersionExceptions 那就是并发错误

2.3 一对多提交

只处理主表数据就行了,从表不需要考虑,因为是一起提交。

三、悲观锁的用法

悲观锁适合用于 读取和插入在同一个步骤下的操作,并且禁止2个请求同时操作

3.1 悲观锁等待模式

🎯定义:2个相同的业务代码 同时执行时必须等待 第一个执行成功后执行。

主键查询一般是行锁,如果非主键可以会变成表锁。


db.BeginTran();
//查询条件记录后锁表
var data=db.Queryable<Order>().TranLock(DbLockType.Wait).Where(it=>it.Id==1).ToList();//返回条数尽量最少尽量主键
//插入、更新等操作
.......
db.CommitTran();
 
//异常要加上
db.RollBackTran();

3.2 悲观锁排它模式

🎯定义:2个相同的业务代码 同时执行时只会生效一个,其它都扔出错误。

db.BeginTran();
//查询条件记录后锁表
var data = db.Queryable<Order>().TranLock(DbLockType.Error).Where(it=>it.Name=="a").ToList();//返回条数尽量最少 for update UPDLOCK
//插入、更新等操作 
.......
db.CommitTran();
 
//异常要加上
db.RollBackTran();

测试代码:

用的来验证是否扔出异常


for (int i = 0; i < 10; i++)
{
    Task.Run(() =>
    {
            var db = GetInstance();//用的sqlsugarclient保证db线程安全每次New一下
        try
        {
          
            db.BeginTran();
            var getAll = db.Queryable<Order>().TranLock(DbLockType.Error).ToList();
            System.Threading.Thread.Sleep(1000);
            db.CommitTran();
            Console.WriteLine("成功");
        }
        catch (Exception ex)
        {
            db.RollBackTran();
            Console.WriteLine("失败");
        }
    });
}

在这里插入图片描述

🎀🎀🎀 .NET开源 ORM 框架 SqlSugar 系列 🎀🎀🎀

【开篇】.NET开源 ORM 框架 SqlSugar 系列
【入门必看】.NET开源 ORM 框架 SqlSugar 系列
【实体配置】.NET开源 ORM 框架 SqlSugar 系列
【Db First】.NET开源 ORM 框架 SqlSugar 系列
【Code First】.NET开源 ORM 框架 SqlSugar 系列
【数据事务】.NET开源 ORM 框架 SqlSugar 系列
【连接池】.NET开源 ORM 框架 SqlSugar 系列
【查询目录】.NET开源 ORM 框架 SqlSugar 系列
【查询基础】.NET开源 ORM 框架 SqlSugar 系列
【排序用法】.NET开源 ORM 框架 SqlSugar 系列
【分组去重】.NET开源 ORM 框架 SqlSugar 系列
【联表查询】.NET开源 ORM 框架 SqlSugar 系列
【导航查询】.NET开源 ORM 框架 SqlSugar 系列
【子查询】.NET开源 ORM 框架 SqlSugar 系列
【嵌套查询】.NET开源 ORM 框架 SqlSugar 系列
【配置查询】.NET开源 ORM 框架 SqlSugar 系列
【并集查询】.NET开源 ORM 框架 SqlSugar 系列
【树型查询】.NET开源 ORM 框架 SqlSugar 系列
【表格查询】.NET开源 ORM 框架 SqlSugar 系列
【动态表达式】.NET开源 ORM 框架 SqlSugar 系列
【查询函数】.NET开源ORM框架 SqlSugar 系列
【过滤器】.NET开源 ORM 框架 SqlSugar 系列
【跨库查询、多库查询】.NET开源 ORM 框架
​【报表查询】.NET开源ORM框架 SqlSugar 系列
【Where语法全解密】.NET开源ORM框架 SqlSugar 系列
【Select 语法全解密】.NET开源ORM框架 SqlSugar 系列
【查询返回结果类型】.NET开源ORM框架 SqlSugar 系列
【insert 插入数据语法合集】.NET开源ORM框架 SqlSugar 系列
【SqlSugar雪花ID常见问题】.NET开源ORM框架 SqlSugar 系列
【update 更新数据语法合集】.NET开源ORM框架 SqlSugar 系列


在这里插入图片描述

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

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

相关文章

DeepSeek-R1本地搭建

1. 前言 现在deepseek火上天了&#xff0c;因为各种应用场景,加上DeepSeek一直网络异常&#xff0c;所以本地部署Deepseek成为大家的另一种选择。 目前网络上面关于DeepSeek的部署方式有很多&#xff0c;但是太麻烦了&#xff0c;本文是一篇极为简单的DeepSeek本地部署方式&…

查出 product 表中所有 detail 字段包含 xxx 的完整记录

您可以使用以下 SQL 查询语句来查出 product 表中所有 detail 字段包含 oss.kxlist.com 的完整记录&#xff1a; SELECT * FROM product WHERE INSTR(detail, oss.kxlist.com) > 0;下面是detail字段包含的完整内容 <p><img style"max-width:100%;" src…

Redis存储⑥Redis五大数据类型之 Zset

目录 1. Zset 有序集合 1.1 Zset 有序集合常见命令 zadd zcard zcount zrange zrevrange zrangebyscore&#xff08;弃用&#xff09; zpopmax bzpopmax zpopmin bzpopmin zrank zrevrank zscore zrem zremrangebyrank zremrangebyscore zincrby 1.2 Zset有…

将Excel中的图片保存下载并导出

目录 效果演示 注意事项 核心代码 有需要将excel中的图片解析出来保存到本地的小伙子们看过来&#xff01;&#xff01;&#xff01; 效果演示 注意事项 仅支持xlsx格式&#xff1a;此方法适用于Office 2007及以上版本的.xlsx文件&#xff0c;旧版.xls格式无法使用。 图片名…

SQL注入之布尔和时间盲注,sqli-labs

实验环境&#xff1a; sqli-labs&#xff0c;小皮面板搭建&#xff0c;edge浏览器 apache&#xff1a;2.4.39&#xff0c;MySQL&#xff1a;5.7 PHP&#xff1a;5.39 Python&#xff08;pycharm2023&#xff09;:3 less-8 布尔盲注&#xff1a; 1.我这里是采用最简单的直接采…

基于云计算、大数据与YOLO设计的火灾/火焰目标检测

摘要&#xff1a;本研究针对火灾早期预警检测需求&#xff0c;采用在Kaggle平台获取数据、采用云计算部署的方式&#xff0c;以YOLO11构建模型&#xff0c;使用云计算服务器训练模型。经训练&#xff0c;box loss从约3.5降至1.0&#xff0c;cls loss从约4.0降至1.0&#xff0c;…

YOLO自定义数据集实现K折交叉验证——K-Fold Cross Validation

实现K折交叉验证&#xff08;K-Fold Cross Validation&#xff09;对于YOLO&#xff08;You Only Look Once&#xff09;自定义数据集的目标检测任务可以显著提升模型的可靠性和泛化能力。 1. 数据集准备 首先&#xff0c;你需要确保你的数据集符合YOLO的格式&#xff0c;具体…

go语言简单快速的按顺序遍历kv结构(map)

文章目录 需求描述用map实现按照map的key排序用二维切片实现用结构体实现 需求描述 在go语言中&#xff0c;如果需要对map遍历&#xff0c;每次输出的顺序是不固定的&#xff0c;可以考虑存储为二维切片或结构体。 假设现在需要在页面的下拉菜单中展示一些基础的选项&#xff…

【竞技宝】LOL-LPL:EDG3-0零封LNG

北京时间2月12日,英雄联盟LPL2025正在如火如荼的进行之中,昨日迎来LNG对阵EDG,以下是本场比赛的详细战报。 第一局: EDG:杰斯、赵信、维克托、女枪、芮尔 LNG:猴子、猪妹、飞机、韦鲁斯、布隆 首局比赛,EDG在蓝色方,LNG在红色方。阵容方面,EDG点出了杰斯、赵信、维克托、女枪…

在fedora41中安装钉钉dingtalk_7.6.25.4122001_amd64

在Fedora-Workstation-Live-x86_64-41-1.4中安装钉钉dingtalk_7.6.25.4122001_amd64.deb 到官网下载钉钉Linux客户端com.alibabainc.dingtalk_7.6.25.4122001_amd64.deb https://page.dingtalk.com/wow/z/dingtalk/simple/ddhomedownload#/ 一、直接使用dpkg命令安装deb包报错…

看期货用的指标,可以提示买卖点和K线转折变颜色的主图指标源码下载

A:MA(CLOSE,17)ABS(MA(CLOSE,17)-REF(MA(CLOSE,17),1)); B:MA(CLOSE,17)MA(CLOSE,17)-REF(MA(CLOSE,17),1); 分界线:IF(MA(CLOSE,17)<B,B,MA(CLOSE,17)),COLORFF00FF,LINETHICK2; 操作线:分界线-(EMA(C,3)-分界线),COLOR00FFFF,LINETHICK2; GUP:MA(C,5),COLORWHITE,LINE…

【PS 2022】Adobe Genuine Service Alert 弹出

电脑总是弹出Adobe Genuine Service Alert弹窗 1. 不关掉弹窗并打开任务管理器&#xff0c;找到Adobe Genuine Service Alert&#xff0c;并右键进入文件所在位置 2 在任务管理器中结束进程并将文件夹中的 .exe 文件都使用空文档替换掉 3. 打开PS不弹出弹窗&#xff0c;解决&a…

30天开发操作系统 第 20 天 -- API

前言 大家早上好&#xff0c;今天我们继续努力哦。 昨天我们已经实现了应用程序的运行, 今天我们来实现由应用程序对操作系统功能的调用(即API, 也叫系统调用)。 为什么这样的功能称为“系统调用”(system call)呢&#xff1f;因为它是由应用程序来调用(操作)系统中的功能来完…

蓝桥杯(B组)-每日一题(求最大公约数最小公倍数)

题目&#xff1a; 代码展现&#xff1a; #include<iostream> using namespace std; int main() {int m,n,x,y;cin>>m>>n;//输入两个整数int b;bm%n;//取余数xm;//赋值yn;while(b)//当余数不为0的时候{xy;//辗转相除求最小公约数yb;bx%y;}cout<<y<&…

arduino扩展:Arduino Mega 控制 32 个舵机(参考表情机器人)

参考&#xff1a;表情机器人中使用22个舵机的案例 引言 在电子制作与自动化控制领域&#xff0c;Arduino 凭借其易用性和强大的扩展性备受青睐。Arduino Mega 作为其中功能较为强大的一款开发板&#xff0c;具备丰富的引脚资源&#xff0c;能够实现复杂的控制任务。舵机作为常…

基于51单片机的门禁刷卡器proteus仿真

地址&#xff1a;https://pan.baidu.com/s/1j0KAmH5pVGWZWRpT6p5hBg 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectron…

mapbox进阶,添加绘图扩展插件,裁剪线

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️MapboxDraw 绘图控件二、🍀添加绘图扩…

19.4.6 读写数据库中的二进制数据

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 需要北风数据库的请留言自己的信箱。 北风数据库中&#xff0c;类别表的图片字段在【数据表视图】中显示为Bitmap Image&#xff1…

MapReduce到底是个啥?

在聊 MapReduce 之前不妨先看个例子&#xff1a;假设某短视频平台日活用户大约在7000万左右&#xff0c;若平均每一个用户产生3条行为日志&#xff1a;点赞、转发、收藏&#xff1b;这样就是两亿条行为日志&#xff0c;再假设每条日志大小为100个字节&#xff0c;那么一天就会产…

Winform自定义控件与案例 - 构建炫酷的自定义环形进度条控件

文章目录 1、控件效果2、案例实现1、代码实现2、代码解释3、使用示例 4、总结 1、控件效果 2、案例实现 1、代码实现 代码如下&#xff08;示例&#xff09;&#xff1a; using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; …