0

0

c# 高并发下的数据库操作优化 c# EF Core并发处理

煙雲

煙雲

发布时间:2026-01-18 10:09:08

|

791人浏览过

|

来源于php中文网

原创

ef core 的 savechangesasync 在高并发下卡住或抛异常,根本原因是多个线程共用同一 dbcontext 实例(非线程安全)或未处理数据库并发冲突;正确做法是注册为 scoped、避免跨 await 复用、启用 rowversion 乐观并发控制、高频操作改用原生 sql 或批量库。

c# 高并发下的数据库操作优化 c# ef core并发处理

EF Core 的 SaveChangesAsync 在高并发下为什么会卡住或抛出异常

根本原因不是 EF Core 本身“不支持并发”,而是多个线程/请求共用同一个 DbContext 实例,或在未处理数据库层面并发冲突的情况下直接提交修改。EF Core 默认的 DbContext 是**短生命周期、非线程安全**的——它不能被多个线程同时调用 SaveChangesAsync,否则会触发 InvalidOperationException: A second operation started on this context before a previous operation completed

常见误用场景包括:把 DbContext 注册为 Singleton、在异步任务中复用同一实例、或在 Web API 中手动 new 出一个长期存活的上下文。

  • Web 应用必须将 DbContext 注册为 Scoped(ASP.NET Core 默认行为),确保每个 HTTP 请求独占一个实例
  • 后台任务(如 IHostedService)需自行创建作用域
    using var scope = _serviceProvider.CreateScope();
    var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
  • 绝对不要跨 await 边界持有并复用同一个 DbContext 实例

乐观并发控制:用 [ConcurrencyCheck]RowVersion 避免脏写

当多个请求几乎同时读取同一条记录、各自修改后提交,后提交者会覆盖前者的变更(丢失更新)。EF Core 提供两种主流乐观并发方案,推荐优先使用 byte[] 类型的 RowVersion 字段(SQL Server 的 rowversion / PostgreSQL 的 xmin / SQLite 的 sqlite_version 语义等效列)。

[Timestamp][ConcurrencyCheck] 属性标记后,EF Core 会在 UPDATE 语句的 WHERE 子句中加入该字段原始值。若数据库中该值已变(说明被他人改过),则 SaveChangesAsync 返回 0 行受影响,并抛出 DbUpdateConcurrencyException

95Shop仿醉品商城
95Shop仿醉品商城

95Shop可以免费下载使用,是一款仿醉品商城网店系统,内置SEO优化,具有模块丰富、管理简洁直观,操作易用等特点,系统功能完整,运行速度较快,采用ASP.NET(C#)技术开发,配合SQL Serve2000数据库存储数据,运行环境为微软ASP.NET 2.0。95Shop官方网站定期开发新功能和维护升级。可以放心使用! 安装运行方法 1、下载软件压缩包; 2、将下载的软件压缩包解压缩,得到we

下载
  • 实体定义示例:
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        [Timestamp] // 自动映射为 byte[]
        public byte[] RowVersion { get; set; }
    }
  • 捕获并发异常后应重试(而非静默失败):
    try
    {
        await context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException ex)
    {
        foreach (var entry in ex.Entries)
        {
            entry.OriginalValues.SetValues(entry.GetDatabaseValues());
        }
        // 可选择重试一次,或返回 409 Conflict 给客户端
    }
  • 避免对非主键字段(如 UpdatedAt)做 [ConcurrencyCheck] —— 它无法保证原子性,且易因时钟不同步导致误判

批量操作别硬扛:绕过 EF Core 走原生 SQL 或专用库

高频小更新(如计数器 +1、状态流转)用 EF Core 逐条 SaveChangesAsync 会产生严重性能瓶颈:每条语句都经历变更跟踪、生成 SQL、参数绑定、网络往返。即使开启 AsNoTracking(),也无法规避 ORM 层开销。

真正有效的做法是「该用原生就用原生」:

  • 单字段原子更新(如点赞数+1):
    await context.Database.ExecuteSqlInterpolatedAsync(
        $"UPDATE Posts SET LikesCount = LikesCount + 1 WHERE Id = {postId}");
  • 批量插入/更新:用 Microsoft.Data.Sqlite(SQLite)、Npgsql(PostgreSQL)或 SqlBulkCopy(SQL Server)直连;或引入 EFCore.BulkExtensions 这类成熟扩展库
  • 避免在循环里反复调用 SaveChangesAsync —— 即使是 Scoped 上下文,也应聚合变更后一次性提交,除非业务强要求每步独立事务

连接池与事务边界:别让 BeginTransaction 成为并发瓶颈

EF Core 默认每个 SaveChangesAsync 都自动包裹在隐式事务中。高并发下大量短事务会加剧数据库连接争用和日志写入压力。显式控制事务时更需谨慎:

  • 只在真正需要 ACID 保证的场景才用 context.Database.BeginTransaction();多数读写分离操作无需手动事务
  • 避免长事务:事务持续时间越长,锁持有越久,死锁风险越高。尤其不要在事务内执行 HTTP 调用、文件 IO 或长时间计算
  • 确认数据库连接字符串已启用连接池(SQL Server 默认开启;PostgreSQL 需检查 Pooling=true);连接池大小不足会导致 Timeout expired,可通过 Max Pool Size 调整,但优先排查是否连接泄漏(如忘记 await 或未释放 DbContext

并发问题从来不在“要不要用 EF Core”,而在于是否清楚每个 API 调用背后发生了什么——比如 SaveChangesAsync 不只是发 SQL,它还同步变更跟踪器、校验约束、触发事件。跳过这些环节的时机和方式,才是优化的关键分水岭。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

1133

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

340

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

381

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2152

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

380

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

1663

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

585

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

440

2024.04.29

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Java 教程
Java 教程

共578课时 | 80.6万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号