首页 > 其他分享 >EFCore乐观并发控制

EFCore乐观并发控制

时间:2022-09-26 09:37:16浏览次数:43  
标签:控制 令牌 string 乐观 并发 EFCore Owner public

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

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

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

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

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

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

乐观并发控制:

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

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

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

 public class House
    {
        public const string TABLE = "House";
        public long Id { get; set; }
        public string Name { get; set; }
        public string? Owner { get; set; }
    }

1. 在数据库上下文ApplicationDbContext中指定并发令牌列

 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}抢走了");
                }
            }
        }

 

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

 

标签:控制,令牌,string,乐观,并发,EFCore,Owner,public
From: https://www.cnblogs.com/friend/p/16729756.html

相关文章

  • 并发原理—如何保证多条指令的原子性(二)
    一、提出问题:一条CPU原语指令如何保证多条指令的原子性从上篇文章我们知道当多个CPU访问(此处访问的含义不仅有读取内存数据的意思,同时也有往内存写入数据的意思)同一个数据......
  • Spring Cloud与Docker高并发微服务架构设计实施 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1UEa0pb5JSp2lIIcFwzapEw点击这里获取提取码 ......
  • 认识线程,初始并发
    线程学习1. 什么是线程程序是为完成特定任务,用某种语言编写的一组指令的集合,即指一段静态的代码,静态对象进程是程序的一次执行过程,或是正在运行的一个程序。是一......
  • Google:Andriod 系统前景不容乐观
    据国外媒体报道,相比于谷歌在谷歌网络开发年会GoogleI/O2015上对Andriod系统的乐观,目前Andriod系统在高端智能手机中的市场份额进一步降低,同时Andriod平板电脑也未对消......
  • 并发学习记录13:不可变
    问题的提出日期转换的问题在多线程的环境下做日期转换很可能出现线程安全问题:代码:@Slf4j(topic="ch.UnchangeTest01")publicclassUnchangeTest01{publicst......
  • 编程规约-并发处理-锁
    编程规约-并发处理-锁锁考量锁的性能损耗高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。......
  • 编程规约-并发处理
    编程规约-并发处理线程安全保证线程安全获取单例对象需要保证线程安全,其中的方法也要保证线程安全。说明:资源驱动类、工具类、单例工厂类都需要注意。SimpleDateForma......
  • Java并发之ReentrantLock基础(一)
    ReentrantLock是Java中java.util.concurrent.locks.Lock的一个实现类,顾名思义它是Java中锁的一种实现,具体一点来说它是Java中一种可重入的独占锁。它与synchronized相比在......
  • EFCore——想查关联数据,不使用外键的实现方式
    EFCore中如何移除主外键关系-走看看(zoukankan.com)EFCore迁移命令移除外键-i没昵称-博客园(cnblogs.com)......
  • 系统架构与设计(2)- 如何设计百万日活用户的高并发系统数据库架构
     对于一个支撑日活百万用户的高并系统,如何设计它的数据库架构?看到这个题目,很多人第一反应就是:分库分表啊!但是实际上,数据库层面的分库分表到底是用来干什么的,它的不同......