EFCore批量操作,你真的清楚吗
背景
EntityFramework Core有许多新的特性,其中一个重要特性便是批量操作。批量操作意味着不需要为每次Insert/Update/Delete操作发送单独的命令,而是在一次SQL请求中发送批量组合指令。
EFCore批量操作实践
批处理是期待已久的功能,社区多次提出要求。现在EFCore支持开箱即用确实很棒,可以提高应用程序的性能和速度。
1
对比实践
以常见的批量插入为例,使用SQL Server Profiler观察产生并执行的SQL语句。
// category表添加3条记录并执行保存using (var c= new SampleDBContext()){ c.Categories.Add(new Category() { CategoryID = 1, CategoryName = "Clothing" }); c.Categories.Add(new Category() { CategoryID = 2, CategoryName = "Footwear" }); c.Categories.Add(new Category() { CategoryID = 3, CategoryName = "Accessories" }); c.SaveChanges();}
当执行SaveChanges(), 从SQL Profiler追溯到的SQL:
exec sp_executesql N'SET NOCOUNT ON;INSERT INTO [Categories] ([CategoryID], [CategoryName])VALUES (@p0, @p1),(@p2, @p3),(@p4, @p5);',N'@p0 int,@p1 nvarchar(4000),@p2 int,@p3 nvarchar(4000),@p4 int,@p5 nvarchar(4000)',@p0=1,@p1=N'Clothing',@p2=2,@p3=N'Footwear',@p4=3,@p5=N'Accessories'
如你所见,批量插入没有产生3个独立的语句,而是被组合为一个传参存储过程脚本(用列值作为参数);如果使用EF6执行相同的代码,则在SQL Server Profiler中将看到3个独立的插入语句 。下面是EFCore、EF6批量插入的对比截图:
① 就性能和速度而言,EFCore批量插入更具优势
② 若数据库是针对云部署,EF6运行这些查询,还将产生额外的流量成本
经过验证:EFCore批量更新、批量删除功能,EFCore均发出了使用sp_executesql存储过程+批量参数构建的SQL脚本。
2
深入分析
起关键作用的存储过程sp_executesql:可以多次执行的语句或批处理 (可带参)
- Syntax for SQL Server, Azure SQL Database, Azure SQL Data Warehouse, Parallel Data Warehouse
sp_executesql [ @stmt = ] statement [ { , [ @params = ] N'@parameter_name data_type [ OUT | OUTPUT ][ ,...n ]' } { , [ @param1 = ] 'value1' [ ,...n ] } ]
注意官方限制:
The amount of data that can be passed by using this method is limited by the number of parameters allowed. SQL Server procedures can have, at most, 2100 parameters. Server-side logic is required to assemble these individual values into a table variable or a temporary table for processing. // SQL存储过程最多可使用2100个参数
3
豁然开朗
SqlServer sp_executesql存储过程最多支持2100个批量操作形成的列值参数,所以遇到很大数量的批量操作,EFCore SqlProvider会帮我们将批量操作分块传输,这也是我们在实际大批量使用时看到分块发送的原因。
EFCore开放了【配置关系型数据库批量操作大小】:
protected override void OnConfiguring(DbContextOptionsBuilder optionbuilder){ string sConnString = @"Server=localhost;Database=EFSampleDB;Trusted_Connection=true;"; optionbuilder.UseSqlServer(sConnString , b => b.MaxBatchSize(1)); // 批量操作的SQL语句数量,也可设定为1禁用批量插入}
总结
① EFCore 相比EF6,已经支持批量操作,能有效提高应用程序的性能
② EFCore的批量操作能力,由对应的DataBaseProvider支撑(Provider实现过程跟背后的存储载体密切相关);关注SQL存储过程sp_executesql,官方明文显示批量操作的列值参数最多2100个,这个关键因素决定了在大批量操作的时候 依旧会被分块传输。
③ 另外一个批量操作的方法,这里也点一下:构造Rawsql 【EFCore也支持Rawsql】
sqlite不支持存储过程,为批量插入提高性能,可采用此方案:
var insertStr = new StringBuilder();insertStr.AppendLine("insert into ProfileUsageCounters (profileid,datetime,quota,usage,natureusage) values");var txt = insertStr.AppendLine(string.Join(',', usgaeEntities.ToList().Select(x =>{ return $"({x.ProfileId},{x.DateTime},{x.Quota},{x.Usage},{x.NatureUsage})";}).ToArray()));await _context.Database.ExecuteSqlCommandAsync(txt.ToString());
+ https://github.com/aspnet/EntityFrameworkCore/issues/6604
+ https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/table-valued-parameters?redirectedfrom=MSDN
EFCore批量操作,你真的清楚吗相关推荐
- efcore 批量_EFCore批量操作内幕
背景 EntityFramework Core有许多新的特性,其中一个重要特性是 批量操作. 批量操作意味着不需要为每次Insert/Update/Delete操作发送单独的命令,而是在一次SQL请求 ...
- Docker-HealthCheck指令探测ASP.NET Core容器健康状态
写在前面 HealthCheck 不仅是对应用程序内运行情况.数据流通情况进行检查,还包括应用程序对外部服务或依赖资源的健康检查. 健康检查通常是以暴露应用程序的HTTP端点的形式实施,可用于配置健康 ...
- DDD:聚合根的批量删除是不是可以批量发送请求
背景 搞了近五年的系统开发,总是抱着一种思维模式,用户的一个操作对应一个请求和一个事务,比如:用户选择了N条记录,我就会向服务器发生一个请求,服务器在一个事务中进行处理.前几天在群里一个前辈反问:批量 ...
- CLI or GUI --- 要高效还是要易用? (该文作者的功底真的很深厚啊)
目录(?) [+] 这篇文章很棒 转载过来欣赏地址httpwwwcnitblogcomaddonearchive2008010838581html 要高效还是要易用谈CLI与GUI 前言 定义 ...
- .NET6下周发布真的香,可不少人却只会.NET Framework!
倒计时7天,.NET6+VS2022+C#10将同时发布正式版,宣告.NET步入全新篇章,各种新语法.新框架.新技术都如约而至,令人期待!近年来,.NET跨平台持续推出新版本,开源社区也不断涌现各种优 ...
- EFCore查缺补漏(一):依赖注入
前段时间,在群里潜水的时候,看见有个群友的报错日志是这样的: An unhandled exception was thrown by the application. System.OutOfMem ...
- EFCore查询语句生成流程、让EFCore支持批量Update/Delete/MergeInto
引子 之前发现了一款叫 EFCore.BulkExtensions 的 nuget 包.里面提供了大量的 BulkInsertOrUpdateOrDelete 和 BatchUpdate 的拓展,可以 ...
- .Neter们,你真的应该了解下EFCore3.x
本期导读: 技术文,带你了解关于EntityFrameworkCore3.x的那些事,本文共1493个字,阅读大约需要3分钟.文末福利不要错过哦! 是的各位.Neter,不用怀疑,使用O/RM的开发者 ...
- EFCore Lazy Loading + Inheritance = 干净的数据表 (二)
前言 本篇是上一篇EFCore Lazy Loading + Inheritance = 干净的数据表 (一) [献给处女座的DB First程序猿] 前菜 的续篇.这一篇才是真的为处女座的DB Fi ...
最新文章
- python哪些类型可以作为迭代器_详解Python迭代和迭代器
- 【收藏】Anaconda详细安装使用教程
- C#获取二叉树深度及分层遍历二叉树
- SparkSQL 内置函数的使用(JAVA与Scala版本)
- 连接(交叉连接、内连接、外连接、自连接)
- JMETER 用户自定义的变量
- 动态规划(四)--最长公共子序列
- SpringBoot 自定义监听器(Listener)
- php 父子id,父子关系PHP / MYSQL
- android简单小游戏开发工具,傻瓜化开发Android小游戏
- 部署kubernetes
- 中兴校招c语言在线笔试题,中兴2021校招软件在线笔试题
- OSS定制自定义response header
- SELECT TOP 1 * FROM是什么意思
- 国内运营商的Sim卡在日版iPhone上的使用方法(卡贴安装方法)
- cropper(裁剪图片)插件使用(案例)
- 【毕业设计】基于单片机的便携式空气质量检测仪 - 物联网 嵌入式
- 手机影音最终,软件退出功能的优化
- 小米路由器3G(R3G)刷潘多拉
- PCIe学习笔记之pcie结构和配置空间
热门文章
- 总结 一下UML 类图的关系
- 解决VS2010 beta2 安装后html标签和script智能提示不起作用的问题
- xp删除管理员账户_在Windows XP中从登录屏幕删除用户帐户
- 清华经管计算机金融专业,非量化背景拿下MIT MFin的清华经管学姐,详解MIT金融项目优劣和职业方向...
- Android风格ppt,Material Design风格的快手PPT
- qmediaplayer获取流类型_Java 流API
- django rest framework 过滤 lim分页
- 云堆栈三大服务模式解析
- 【Linux】IPC-消息队列
- SDUT OJ -2892 A