首页 > 数据库 >mysql使用efcore实现乐观并发控制

mysql使用efcore实现乐观并发控制

时间:2023-06-06 20:12:19浏览次数:39  
标签:string House 并发 modelBuilder efcore mysql Owner public

为了避免多个用户同时操作同一个资源造成的并发冲突问题,通常需要进行并发控制。

并发控制分为:乐观和悲观两策略

悲观:悲观并发控制一般采用行锁、表锁等 排它销对资源进行锁定,确保一个时间点只有一个用户在操作被锁定的资源。

 悲观并发控件的使用比较简单,仅对要进行并发控制的资源加上锁即可,但是这种锁是独占排它的,如果系统并发量很大,锁会严重影响性能,如果使用不当,甚至会导致死锁。因此,对于高并发系统,要尽量避免使用悲观策略,改为NoSQL(Redis)。如果必须使用数据库控制并发,尽量采用乐观并发控制。

乐观:乐观并发控制则允许多个用户同时操作同一个资源,但通过并发冲突检测避免并发操作。

和悲观并发控制相比,乐观并发控制不需要显示使用事务,而且也不需要使用锁。

乐观并发控制:

EF Core 使用并发令牌列实现乐观并发控制,并发令牌列就是需要防止并发冲突的列。

乐观并发有以下两种方式,一:并发令牌列,二:记录级并发控件

一、并发令牌列, 仅一个并发列,或者能确定并发列的情况下使用

public class House

   {        public const string TABLE = "House";        public long Id { getset; }        public string Name { getset; }        public string? Owner { getset; }    } protected override void OnModelCreating(ModelBuilder modelBuilder)        {            base.OnModelCreating(modelBuilder);            //指定并发令牌列Owner            modelBuilder.Entity<House>().Property(m => m.Owner).IsConcurrencyToken();            // 配置表名映射            modelBuilder.Entity<House>().ToTable(House.TABLE);        }  

2. 实现并发控制

[HttpPost("{name}")]        public async Task<ActionResult> UpdateOwner(string name)        {            House house = await db.Houses.SingleAsync(m => m.Id == 1);            if (string.IsNullOrEmpty(house.Owner))            {//房子还在,开始抢房                await Task.Delay(5000);                house.Owner = name;                try                {                    await db.SaveChangesAsync();                    return Ok($"{name} 已经抢到房子。");                }                catch (DbUpdateConcurrencyException ex)//捕捉更新并发异常                {//抢房失败                    var entry = ex.Entries.First();                    var dbValues = await entry.GetDatabaseValuesAsync();                    string newOwner = dbValues.GetValue<string>(nameof(House.Owner));                    return BadRequest($"并发冲突,房子已经被{newOwner}抢走");                }            }            else            {//房子已经被别人抢走了                if (house.Owner == name.Trim())                {                    return Ok($"房子已经是你的了,不用抢了");                }                else                {                    return Ok($"很遗憾,这套房子已经被{house.Owner}抢走了");                }            }        }

二、记录级并发控件,需更新多列,或者事先无法确定需要更新的列

 

 1. 实体类

   public class House    {        public const string TABLE = "House";        public long Id { getset; }        public string Name { getset; }        public string? Owner { getset; }        /// <summary>        /// 时间戳,对应数据库 Timestamp 类型        /// </summary>        public byte[] RowVersion { getset; }    }  

2. 配置DB

  protected override void OnModelCreating(ModelBuilder modelBuilder)        {            base.OnModelCreating(modelBuilder);            //每次更新数据时,RowVersion列会自动生成新值            modelBuilder.Entity<House>().Property(m => m.RowVersion).IsRowVersion();            //设置组合主键              // 配置表名映射            modelBuilder.Entity<House>().ToTable(House.TABLE);        }   转自:https://www.cnblogs.com/friend/p/16729756.html

标签:string,House,并发,modelBuilder,efcore,mysql,Owner,public
From: https://www.cnblogs.com/wugh8726254/p/17461599.html

相关文章

  • 熄灯之后的学习——再读《MySQL必知必会》(6)|| 数据过滤
    操作符:用来联结或改变where子句中的子句的关键字。使用and操作符给where子句附加条件:使用or操作符指示检索任一匹配条件:计算次序:任何时候使用具有and和or操作符的where子句时,都应该使用圆括号明确地分组操作符in操作符用来指定条件范围,范围中的每个条件都可以进......
  • 熄灯之后的学习——再读《MySQL必知必会》(5)|| 过滤数据
    搜索条件(过滤条件):只检索所需数据需要指定的。where子句在表名(from子句)之后给出,在同时使用orderby和where子句的时候,应该让orderby位于where之后。检查单个值:不匹配检查范围检查空值检查......
  • 熄灯之后的学习——再读《MySQL必知必会》(4)|| 排序数据
    子句(clause):SQL语句由子句构成,有些子句是必须的,而有的是可选的。一个子句通常由一个关键字和所提供的数据组成。orderbyxxx指定以xxx列进行排序按多个列排序:只要指定列名,列名之间用逗号分开即可。在按多个列进行排序的时候,排序完全按所规定的顺序进行。降序排序:必须指定DES......
  • 熄灯之后的学习——再读《MySQL必知必会》(3)
    SQL语句不区分大小写多条SQL语句必须以;进行分隔多数SQL人员认为,将SQL语句分成多行更容易阅读和调试SELECT*FROMTABLENAME;返回名为TABLENAME的表的所有列的数据,也可以选择单个列或多个列(多个列的时候,每个列,名用,`分隔开)*是通配符检索不同的行SELECTDISTINCT*......
  • 熄灯之后的学习——再读《MySQL必知必会》(2)
    命令用;结束,仅仅按Enter不执行命令输入help或\h获得帮助输入quit或者exit退出命令行程序关键字(keyword):作为MySQL语言组成部分的一个保留字SHOWDATABASES;返回可用数据库的一个列表。USEDATABASENAME;使用名为DATABASENAME的数据库,该语句不返回任何结果。SHO......
  • 使用Navicat导入《MySQL必知必会》书上用例数据库的方法
    在Navicat中新建一个名为mysqk_crash_course的数据库此数据库初始为空接着将下载好的的sql文件导入完成:再导入另一个sql文件:完成:大功告成:书中用例sql文件下载地址......
  • 熄灯之后的学习——再读《MySQL必知必会》(1)
    熄灯之后一边看视频,一边coding实在麻烦,遂熄灯之后改学习其他内容数据库(database):保存有组织的数据的容器(通常是一个文件或一组文件)。表(table):某种特定类型数据的结构化清单。模式(schema):关于数据库和表的布局及特性。列(column):表中的一个字段。所有表都是由一个或多个列组成的。数据......
  • MYSQL增删改
                     ......
  • mysql5.5.20的安装步骤
    Mysql5.5.20的安装步骤:思路: 1. groupadd-rmysql useradd-gmysql-s/sbin/nologin-Mmysql tarzvxf/root/mysql-5.5.20-linux2.6-x86_64.tar.gz mkdir-p/usr/local/mysql mvmysql-5.5.20-linux2.6-x86_64/*/usr/local/mysql cd/usr/local/mysql/ chow......
  • Fatal error: Can't open and lock privilege tables: Table 'mysql.host' doesn't ex
    mysql安装报错如下:Fatalerror:Can'topenandlockprivilegetables:Table'mysql.host'doesn'texist12121723:10:40mysqld_safemysqldfrompidfile/data/mysql/data/DB8.pidended 解决办法:mysql_install_db--user=mysql 初始化数据库即可   ......