C#【EF Core框架】使用乐观锁处理并发冲突
读本文前先掌握乐观锁和悲观锁的概念
使用乐观锁处理并发冲突
数据库并发指的是多个进程或用户同时访问或更改数据库中的相同数据的情况。 并发控制指的是用于在发生并发更改时确保数据一致性的特定机制。
EF Core 实现乐观并发控制,这意味着它将允许多个进程或用户独立进行更改而不产生同步或锁定的开销。 在理想情况下,这些更改将不会相互干扰,因此都能够成功。 在最坏的情况下,两个或更多进程将尝试进行冲突更改,其中只有一个进程应该成功。
并发控制在 EF Core 中的工作原理
配置为并发令牌的属性用于实现乐观并发控制:每当在 SaveChanges
期间执行更新或删除操作时,会将数据库上的并发令牌值与通过 EF Core 读取的原始值进行比较。
- 如果这些值匹配,则可以完成该操作。
- 如果这些值不匹配,EF Core 会假设另一个用户已执行冲突操作,并中止当前事务。
另一个用户已执行与当前操作冲突的操作的情况称为并发冲突。
数据库提供程序负责实现并发令牌值的比较。
在关系数据库上,EF Core 包括对任何 UPDATE
或 DELETE
语句的 WHERE
子句中的并发令牌值的检查。 执行这些语句后,EF Core 会读取受影响的行数。
如果未影响任何行,将检测到并发冲突,并且 EF Core 会引发 DbUpdateConcurrencyException
。
例如,我们可能希望将 Person
上的 LastName
配置为并发令牌。 则针对用户的任何更新操作将包括 WHERE
子句中的并发检查:
SQL复制
UPDATE [Person] SET [FirstName] = @p1
WHERE [PersonId] = @p0 AND [LastName] = @p2;
解决并发冲突
继续前面的示例,如果一个用户尝试保存对 Person
所做的某些更改,但另一个用户已更改 LastName
,则将引发异常。
此时,应用程序可能只需通知用户由于发生冲突更改而导致更新未成功,然后继续操作。 但可能需要提示用户确保此记录仍表示同一实际用户并重试该操作。
此过程是解决并发冲突的一个示例。
解决并发冲突涉及将当前 DbContext
中挂起的更改与数据库中的值进行合并。 要合并的值将根据应用程序的不同而有所不同,并且可能由用户输入指示。
有三组值可用于帮助解决并发冲突:
- “当前值”是应用程序尝试写入数据库的值。
- “原始值”是在进行任何编辑之前最初从数据库中检索的值。
- “数据库值”是当前存储在数据库中的值。
处理并发冲突的常规方法是:
- 在
SaveChanges
期间捕获DbUpdateConcurrencyException
。 - 使用
DbUpdateConcurrencyException.Entries
为受影响的实体准备一组新更改。 - 刷新并发令牌的原始值以反映数据库中的当前值。
- 重试该过程,直到不发生任何冲突。
在下面的示例中,将 Person.FirstName
和 Person.LastName
设置为并发令牌。 在包括应用程序特定逻辑以选择要保存的值的位置处有一条 // TODO:
注释。
注意需要在实体类需要进行乐观锁的属性标记为[ConcurrencyCheck]
[Table("Infrastructure_User")]public class Infrastructure_User{[Key][Required][Column("userId")]public int UserId { get; set; }//需要进行乐观锁比较的标记[ConcurrencyCheck][Column("displayName")]public string DisplayName { get; set; }[Column("login")]public string Login { get; set; }}
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
namespace EFLearn
{class Program{static async System.Threading.Tasks.Task Main(string[] args){ApplicationDbContext context = new ApplicationDbContext();var items = context.Source.First();items.DisplayName = "管理员2";context.Database.ExecuteSqlRaw("update infrastructure_User set DisplayName='管理员1' where userid=1");var saved = false;while (!saved){try{// Attempt to save changes to the databasecontext.SaveChanges();saved = true;}catch (DbUpdateConcurrencyException ex){foreach (var entry in ex.Entries){if (entry.Entity is Infrastructure_User){var proposedValues = entry.CurrentValues;var databaseValues = entry.GetDatabaseValues();foreach (var property in proposedValues.Properties){var proposedValue = proposedValues[property];var databaseValue = databaseValues[property];}entry.OriginalValues.SetValues(databaseValues);}else{throw new NotSupportedException("Don't know how to handle concurrency conflicts for "+ entry.Metadata.Name);}}}}Console.WriteLine("执行结束");}}
}
下一篇 C#【EF Core框架】进行数据库事务处理https://blog.csdn.net/lichao19897314/article/details/122881390
C#【EF Core框架】使用乐观锁处理并发冲突相关推荐
- mysql乐观锁解决并发冲突
为什么会产生并发冲突? 悲观锁并发性太差 高并发场景用户体验差 实现目标:既要保证用户体验 也要实现数据可靠,乐观锁来解决. 这里有个问题:如果某个时刻只能有一个操作成功,那么其他操作失败怎么办? 前 ...
- mysql 乐观锁_使用Mysql乐观锁解决并发问题
使用mysql乐观锁解决并发问题 案例说明 银行两操作员同时操作同一账户.比如A.B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户扣除50元,A先提交,B后 ...
- mysql使用条件限制乐观锁_使用Mysql乐观锁解决并发问题
使用mysql乐观锁解决并发问题 案例说明 银行两操作员同时操作同一账户.比如A.B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户扣除50元,A先提交,B后 ...
- mysql使用条件限制乐观锁_mysql乐观锁解决并发问题
博客2:https://www.cnblogs.com/laoyeye/p/8097684.html 1.使用版本号实现乐观锁 版本号的实现方式有两种,一个是数据版本机制,一个是时间戳机制.具体如下. ...
- 悲观锁和乐观锁_悲观锁和乐观锁处理并发操作
本人在金融公司任职,今天来分享下关于转账的一些并发处理问题,这节内容,我们不聊实现原来,就单纯的看看如何实现 废话不多说,咱们直接开始,首先我会模拟一张转账表 如下图所示: image.png 一张简 ...
- java乐观锁实现案例
简单说说乐观锁.乐观锁是相对于悲观锁而言.悲观锁认为,这个线程,发生并发的可能性极大,线程冲突几率大,比较悲观.一般用synchronized实现,保证每次操作数据不会冲突.乐观锁认为,线程冲突可能性 ...
- 第四节:EF Core的并发处理
1.说明 和EF版本的并发处理方案一致,需要知道乐观并发和悲观并发的区别,EF Core只支持乐观并发:监控并发的两种方案:监测单个字段和监测整条数据,DataAnnotations 和 Fluent ...
- efcore调用函数_如何在EF Core 使用存储过程
使用EF Core框架能快速的帮助我们进行常规的数据处理和项目开发,但是ORM虽然好用,但是在许多复杂逻辑的数据处理时,我个人还是偏向用SQL和存储过程的方式去处理,但是研究了一下目前最新版本的EF ...
- 跟我一起学.NetCore之EF Core 实战入门,一看就会
前言 还记得当初学习数据库操作时,用ADO.NET一步一步地进行数据操作及查询,对于查询到的数据还得对其进行解析,然后封装返回给应用层:遇到这种重复而繁琐的工作,总有一些大神或团队对其进行封装,从而出 ...
最新文章
- [LeetCode]Implement Trie (Prefix Tree)
- windows下二进制mysql的卸载以及安装教程
- idea 将普通Java项目打包成可直接执行的jar
- JMeter入门,测试计划编写(http请求)
- PHP的工作原理和生命周期
- python print()内置函数
- Lynis 检测自身安全漏洞工具(本机)
- qq流浏览器网页版_如何使QQ浏览器浏览简洁
- HDU 2563 统计问题 (DFS + 打表)
- iptables小案例
- laravel ::all() 选择字段_Laravel 性能优化:优化 ORM 性能使应用程序高可用
- paip.读取WEB.XML中的参数值总结
- 22数学建模美赛 22美赛C题
- 打印计算机错误,打印机测试错误 原因administrator解决办法
- python 苹果李子橙_分享|苹果和它千万不能放在一起!因为它们会……
- ibm大型机服务器虚拟化,PowerVM:IBM小型机虚拟化的利器
- 网站建设服务器拼租服务器好还是独立服务器好
- 运算放大器的环路补偿-关于并联的电阻电容的分析
- java List复制:浅拷贝与深拷贝
- Markdown Day01
热门文章
- No ‘Access-Control-Allow-Origin‘ header is present on the requested resource Vue配置代理解决跨域问题
- 三个等于符号 和两个等于符号的区别
- 阿里大数据平台MaxCompute初窥
- python常用写法
- Softing参加ASAM中国区域大会暨C-ASAM技术论坛会议
- Android动画(翻牌抽奖)
- HTML5 table表格合并单元格和合并边框
- 分享一套永久免费的ChatGPT使用方法
- 谢惠民,恽自求,易法槐,钱定边编数学分析习题课讲义23.2.3练习题参考解答[来自陶哲轩小弟]...
- AppleWWDRCA.cer证书