深入解析EF Core并发控制:乐观与悲观策略的全面对比与实战应用

news2024/9/21 14:51:45

在这里插入图片描述

1. 前言

在使用EF Core开发应用程序时,并发控制是确保数据一致性的重要机制。EF Core 提供了两种主要的并发控制策略:乐观并发控制和悲观并发控制。它们各自有不同的应用场景和实现方式。本文将详细介绍这两种并发控制的区别、常见的应用场景,并分享一些最佳实践。

2.什么是并发控制?

并发控制是指在多个事务并发访问数据库时,管理它们之间的相互影响,确保数据的一致性和完整性。EF Core 通过乐观并发控制和悲观并发控制来管理并发访问。

1、乐观并发控制

1. 概念

乐观并发控制假设冲突较少发生,因此在更新数据之前不锁定资源。通常通过在数据库表中增加一个“版本号”或“时间戳”字段来检测并发冲突。只有在数据被实际修改时,才会检测到冲突。
在这里插入图片描述

2. 实现方式

在EF Core中,可以通过在模型中使用[Timestamp]属性来实现乐观并发控制。EF Core会在SaveChanges时自动检查数据库中对应行的版本是否已更改。

3. 应用场景

乐观并发控制适用于大部分读多写少的场景,比如:

  • 博客平台:多个用户可能同时编辑自己的文章,但很少会有用户同时编辑同一篇文章。
  • 电商平台的商品详情:用户可以同时查看商品详情,但只有管理员可以编辑商品信息。
4. 示例代码
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Stock { get; set; }
    [Timestamp]
    public byte[] RowVersion { get; set; }
}

public async Task UpdateProductStockAsync(int productId, int newStock)
{
    using var context = new AppDbContext();
    var product = await context.Products.FindAsync(productId);

    if (product != null)
    {
        product.Stock = newStock;
        try
        {
            await context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            Console.WriteLine("并发冲突:该产品已被其他用户更新。");
        }
    }
}
5. 最佳实践
  • 处理并发冲突: 捕获DbUpdateConcurrencyException异常并进行适当的处理,比如重新加载实体或通知用户冲突。
  • 适当使用版本控制: 在可能发生并发冲突的地方添加[Timestamp]RowVersion字段,以便EF Core能有效地管理冲突。

2、悲观并发控制

1. 概念

悲观并发控制假设冲突经常发生,因此在读取数据后,立即锁定资源,直到事务完成,防止其他事务修改数据。这种方式会强制其他操作等待锁定的资源释放后才能继续。
在这里插入图片描述

2. 实现方式

在EF Core中,悲观并发控制通常通过手动管理数据库事务,并结合SQL语句中的锁定选项(如WITH (UPDLOCK)FOR UPDATE)来实现。

3. 应用场景

悲观并发控制适用于冲突频繁且数据一致性要求高的场景,比如:

  • 银行系统的账户转账:为了防止资金超额转账,需要在读取账户余额后立即锁定账户数据。
  • 库存管理系统:在处理高频率库存更新时,确保库存数据不被超卖。
4. 示例代码
public async Task TransferFundsAsync(int fromAccountId, int toAccountId, decimal amount)
{
    using var transaction = await _context.Database.BeginTransactionAsync();

    try
    {
        var fromAccount = await _context.Accounts
            .Where(a => a.Id == fromAccountId)
            .ForUpdate() // 使用行级锁定
            .SingleOrDefaultAsync();

        var toAccount = await _context.Accounts
            .Where(a => a.Id == toAccountId)
            .ForUpdate() // 使用行级锁定
            .SingleOrDefaultAsync();

        if (fromAccount != null && toAccount != null && fromAccount.Balance >= amount)
        {
            fromAccount.Balance -= amount;
            toAccount.Balance += amount;
            await _context.SaveChangesAsync();
            await transaction.CommitAsync();
        }
        else
        {
            await transaction.RollbackAsync();
        }
    }
    catch (Exception)
    {
        await transaction.RollbackAsync();
        throw;
    }
}
5. 最佳实践
  • 谨慎使用锁定: 虽然悲观并发控制可以有效防止并发冲突,但也可能导致性能下降和死锁风险。在必要时才使用。
  • 分解事务: 尽量将事务划分为较小的单元,以减少锁定时间,提高系统并发性能。

3. 乐观并发控制与悲观并发控制的比较

特性乐观并发控制悲观并发控制
假设冲突很少发生冲突频繁发生
实现方式通过版本号或时间戳检测并发冲突通过锁定资源防止并发冲突
应用场景读多写少,冲突少的场景冲突频繁且数据一致性要求高的场景
性能影响性能影响较小可能导致性能下降,尤其在高并发场景
开发复杂度较低较高

4. 结论

在EF Core中,选择乐观并发控制还是悲观并发控制,取决于应用的具体需求。对于大多数读多写少的场景,乐观并发控制是一种性能友好且易于实现的选择。而在冲突频繁发生且数据一致性要求高的场景下,悲观并发控制则显得更加稳妥。无论选择哪种策略,都应根据实际情况进行优化和测试,以确保系统的可靠性和性能。
在这里插入图片描述

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

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

相关文章

fastadmin 文件上传七牛云

1-安装七牛云官方SDK composer require qiniu/php-sdk 2-七牛云配置 <?phpnamespace app\common\controller;use Qiniu\Storage\BucketManager; use think\Config; use Qiniu\Auth; use Qiniu\Storage\UploadManager; use think\Controller; use think\Db;/*** 七牛基类*…

python操作kafka

一、参考阿里云的官方链接&#xff1a; 使用Python SDK接入Kafka收发消息_云消息队列 Kafka 版(Kafka)-阿里云帮助中心 二、安装python环境 三、添加python依赖库 pip install confluent-kafka1.9.2 四、新建一个setting.py文件配置信息 kafka_setting {sasl_plain_user…

爆改YOLOv8|利用SCConv改进yolov8-即轻量又涨点

1&#xff0c;本文介绍 SCConv&#xff08;空间和通道重构卷积&#xff09;是一种高效的卷积模块&#xff0c;旨在优化卷积神经网络&#xff08;CNN&#xff09;的性能&#xff0c;通过减少空间和通道的冗余来降低计算资源的消耗。该模块由两个核心组件构成&#xff1a; 空间重…

斯坦福UE4 C++课学习补充25:寻路EQS

文章目录 一、创建EQS二、修改行为树三、查询上下文 一、创建EQS 场景查询系统EQS&#xff1a;可用于收集场景相关的数据。然后该系统可以使用生成器&#xff0c;通过各种用户定义的测试就这些数据提问&#xff0c;返回符合所提问题类型的最佳项目Item。 EQS的一些使用范例包…

Unity【Colliders碰撞器】和【Rigibody刚体】的应用——小球反弹效果

目录 Collider 2D 定义&#xff1a; 类型&#xff1a; Rigidbody 2D 定义&#xff1a; 属性和行为&#xff1a; 运动控制&#xff1a; 碰撞检测&#xff1a; 结合使用 实用检测 延伸拓展 1、在Unity中优化Collider 2D和Rigidbody 2D的性能 2、Unity中Collider 2D…

香橙派列出附近所有的WiFi

使用 nmcli nmcli 是 NetworkManager 的命令行工具&#xff0c;它可以用来检索和管理网络连接。 nmcli device wifi list这个命令会列出所有周围的WiFi网络。

社区电商系统源码之卷轴模式:商业模式分析

随着互联网技术的发展&#xff0c;电商平台的竞争日益激烈&#xff0c;如何留住用户并提升用户粘性成为了各大电商平台关注的重点。卷轴模式作为一种新兴的用户参与和激励机制&#xff0c;在社区电商系统中得到了广泛的应用。本文将从技术角度探讨卷轴模式在社区电商系统中的实…

rust 命令行工具rsup管理前端npm依赖

学习了一年的 rust 了&#xff0c;但是不知道用来做些什么&#xff0c;也没能赋能到工作中&#xff0c;现在前端基建都已经开始全面进入 rust 领域了&#xff0c;rust 的前端生态是越来越好。但是自己奈何水平不够&#xff0c;想贡献点什么&#xff0c;无从下手。 遂想自己捣鼓…

Leetcode3256. 放三个车的价值之和最大 I

Every day a Leetcode 题目来源&#xff1a;3256. 放三个车的价值之和最大 I 解法1&#xff1a;贪心 从大到下排序矩阵所有值, 记为数组v。 转化此题&#xff1a;从r*c个数中选取3个数分别给到车1&#xff0c;车2&#xff0c;和车3&#xff0c;使得符合条件的三数之和最大。…

rancher upgrade 【rancher 升级】

文章目录 1. 背景2. 下载3. 安装4. 检查5. 测试5.1 创建项目5.2 创建应用5.3 删除集群5.4 注册集群 1. 背景 rancher v2.8.2 升级 v2.9.1 2. 下载 下载charts helm repo add rancher-latest https://releases.rancher.com/server-charts/latest helm repo update helm fetc…

NIO、Reactor模式与直接内存

1.NIO NIO有三大核心组件&#xff1a;Selector选择器、Channel管道、buffer缓冲区。、 1.1Selector Selector的英文含义是“选择器”&#xff0c;也可以称为为“轮询代理器”、“事件订阅器”、“channel容器管理机”都行。 Java NIO的选择器允许一个单独的线程来监视多个输…

鸿蒙MPChart图表自定义(四)短刻度线

对于图表中的x轴效果&#xff0c;我们有时想要实现如图所示的特定刻度线。若需绘制x轴的短刻度线&#xff0c;我们可以利用现有资源&#xff0c;将原本的网格线稍作修改&#xff0c;只需绘制一条简洁的短线即可达到目的。 具体的方法就是写一个类MyXAxisRender继承自XAxisRend…

iOS——runLoop

什么是runloop RunLoop实际上就是一个对象&#xff0c;这个对象管理了其需要处理的事件和消息&#xff0c;并提供了一个入口函数来执行相应的处理逻辑。线程执行了这个函数后&#xff0c;就会处于这个函数内部的循环中&#xff0c;直到循环结束&#xff0c;函数返回。 RunLoo…

【转载】golang内存分配

Go 的分配采用了类似 tcmalloc 的结构.特点: 使用一小块一小块的连续内存页, 进行分配某个范围大小的内存需求. 比如某个连续 8KB 专门用于分配 17-24 字节,以此减少内存碎片. 线程拥有一定的 cache, 可用于无锁分配. 同时 Go 对于 GC 后回收的内存页, 并不是马上归还给操作系…

Android13 Hotseat客制化--Hotseat修改布局、支持滑动、去掉开机弹动效果、禁止创建文件夹

需求如题&#xff0c;实现效果如下 &#xff1a; 固定Hotseat的padding位置、固定高度 step1 在FeatureFlags.java中添加flag,以兼容原生态代码 public static final boolean STATIC_HOTSEAT_PADDING true;//hotseat area fixed step2:在dimens.xml中添加padding值和高度值…

信息系统安全保障

关注这个证书的其他相关笔记&#xff1a;NISP 一级 —— 考证笔记合集-CSDN博客 0x01&#xff1a;信息系统 信息系统是具有集成性的系统&#xff0c;每一个组织中信息流动的综合构成一个信息系统。信息系统是根据一定的需要进行输入、系统控制、数据处理、数据存储与输出等活动…

职场关系课:职场上的基本原则(安全原则、进步原则、收益原则、逃生舱原则)

文章目录 引言安全原则进步原则收益原则逃生舱原则引言 职场上的王者,身体里都应该有三个灵魂: 一个文臣,谨小慎微,考虑风险; 一个武将,积极努力,谋求胜利; 一个商人,精打细算,心中有数。 安全原则 工作安全:保住自己的工作和位置信用安全:保住个人的信用,如果领…

《征服数据结构》差分数组

摘要&#xff1a; 1&#xff0c;差分数组的介绍 2&#xff0c;二维差分数组的介绍 1&#xff0c;差分数组的介绍 差分数组主要是操作区间的&#xff0c;关于区间操作的数据结构比较多&#xff0c;除了前面讲的《稀疏表》&#xff0c;还有树状数组&#xff0c;线段树&#xff0c…

高德地图SDK Android版开发 10 InfoWindow

高德地图SDK Android版开发 10 InfoWindow 前言相关类和方法默认样式Marker类AMap类AMap.OnInfoWindowClickListener 接口 自定义样式(视图)AMap 类AMap.ImageInfoWindowAdapter 接口 自定义样式(Image)AMap.ImageInfoWindowAdapter 接口 示例界面布局MapInfoWindow类常量成员变…

215篇【大模型医疗】论文合集(附PDF)

ChatGPT的横空出世引发了新一轮生成式大模型热潮&#xff0c;作为最新技术的"试验场"&#xff0c;医疗也成为众多大模型的热门首选。 我整理了215篇医疗和大模型的论文&#xff0c;供大家学习和参考。 领215篇医疗和大模型论文