背景

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批量操作,你真的清楚吗相关推荐

  1. efcore 批量_EFCore批量操作内幕

    背景 EntityFramework Core有许多新的特性,其中一个重要特性是 批量操作. 批量操作意味着不需要为每次Insert/Update/Delete操作发送单独的命令,而是在一次SQL请求 ...

  2. Docker-HealthCheck指令探测ASP.NET Core容器健康状态

    写在前面 HealthCheck 不仅是对应用程序内运行情况.数据流通情况进行检查,还包括应用程序对外部服务或依赖资源的健康检查. 健康检查通常是以暴露应用程序的HTTP端点的形式实施,可用于配置健康 ...

  3. DDD:聚合根的批量删除是不是可以批量发送请求

    背景 搞了近五年的系统开发,总是抱着一种思维模式,用户的一个操作对应一个请求和一个事务,比如:用户选择了N条记录,我就会向服务器发生一个请求,服务器在一个事务中进行处理.前几天在群里一个前辈反问:批量 ...

  4. CLI or GUI --- 要高效还是要易用? (该文作者的功底真的很深厚啊)

     目录(?) [+] 这篇文章很棒 转载过来欣赏地址httpwwwcnitblogcomaddonearchive2008010838581html 要高效还是要易用谈CLI与GUI 前言 定义 ...

  5. .NET6下周发布真的香,可不少人却只会.NET Framework!

    倒计时7天,.NET6+VS2022+C#10将同时发布正式版,宣告.NET步入全新篇章,各种新语法.新框架.新技术都如约而至,令人期待!近年来,.NET跨平台持续推出新版本,开源社区也不断涌现各种优 ...

  6. EFCore查缺补漏(一):依赖注入

    前段时间,在群里潜水的时候,看见有个群友的报错日志是这样的: An unhandled exception was thrown by the application. System.OutOfMem ...

  7. EFCore查询语句生成流程、让EFCore支持批量Update/Delete/MergeInto

    引子 之前发现了一款叫 EFCore.BulkExtensions 的 nuget 包.里面提供了大量的 BulkInsertOrUpdateOrDelete 和 BatchUpdate 的拓展,可以 ...

  8. .Neter们,你真的应该了解下EFCore3.x

    本期导读: 技术文,带你了解关于EntityFrameworkCore3.x的那些事,本文共1493个字,阅读大约需要3分钟.文末福利不要错过哦! 是的各位.Neter,不用怀疑,使用O/RM的开发者 ...

  9. EFCore Lazy Loading + Inheritance = 干净的数据表 (二)

    前言 本篇是上一篇EFCore Lazy Loading + Inheritance = 干净的数据表 (一) [献给处女座的DB First程序猿] 前菜 的续篇.这一篇才是真的为处女座的DB Fi ...

最新文章

  1. python哪些类型可以作为迭代器_详解Python迭代和迭代器
  2. 【收藏】Anaconda详细安装使用教程
  3. C#获取二叉树深度及分层遍历二叉树
  4. SparkSQL 内置函数的使用(JAVA与Scala版本)
  5. 连接(交叉连接、内连接、外连接、自连接)
  6. JMETER 用户自定义的变量
  7. 动态规划(四)--最长公共子序列
  8. SpringBoot 自定义监听器(Listener)
  9. php 父子id,父子关系PHP / MYSQL
  10. android简单小游戏开发工具,傻瓜化开发Android小游戏
  11. 部署kubernetes
  12. 中兴校招c语言在线笔试题,中兴2021校招软件在线笔试题
  13. OSS定制自定义response header
  14. SELECT TOP 1 * FROM是什么意思
  15. 国内运营商的Sim卡在日版iPhone上的使用方法(卡贴安装方法)
  16. cropper(裁剪图片)插件使用(案例)
  17. 【毕业设计】基于单片机的便携式空气质量检测仪 - 物联网 嵌入式
  18. 手机影音最终,软件退出功能的优化
  19. 小米路由器3G(R3G)刷潘多拉
  20. PCIe学习笔记之pcie结构和配置空间

热门文章

  1. 总结 一下UML 类图的关系
  2. 解决VS2010 beta2 安装后html标签和script智能提示不起作用的问题
  3. xp删除管理员账户_在Windows XP中从登录屏幕删除用户帐户
  4. 清华经管计算机金融专业,非量化背景拿下MIT MFin的清华经管学姐,详解MIT金融项目优劣和职业方向...
  5. Android风格ppt,Material Design风格的快手PPT
  6. qmediaplayer获取流类型_Java 流API
  7. django rest framework 过滤 lim分页
  8. 云堆栈三大服务模式解析
  9. 【Linux】IPC-消息队列
  10. SDUT OJ -2892 A