.NET 开源 EF Core 批处理扩展工具,真好用

前言

Entity Framework Core(EF Core)作为 .NET 生态系统中受欢迎的对象关系映射器(ORM),其轻量级、可扩展性和支持多个数据库引擎而备受青睐。

本文将介绍一款.NET 的开源 EF Core 批处理扩展工具,它极大地提升了数据处理的效率和性能。来看看如何轻松集成到我们现有的 EF Core 项目中。

EFCore.BulkExtensions

Entity Framework Core (EF Core) 批量扩展库提供了支持批量复制功能的工具,适用于 .NET 平台上的插入、更新、删除、读取(CRUD)、清空表(Truncate)以及保存更改(SaveChanges)等操作。

该库支持 SQL Server、PostgreSQL、MySQL 和 SQLite 数据库。

该库轻量且高效,涵盖了常用的 CRUD 操作,并被微软评为推荐的前 20 个 EF Core 扩展之一。

版本说明

内部机制

SQL Server:使用 SqlBulkCopy 进行插入操作,更新和删除操作则结合了 BulkInsert 和原生 SQL 的 MERGE。

SQLite:由于没有 BulkCopy,该库使用纯 SQL 结合 UPSERT。

注意事项

批量测试:不能使用 UseInMemoryDb,因为 InMemoryProvider 不支持特定的关系数据库方法。

如何使用?

首先使用 Nuget 安装 EFCore.BulkExtensions。

复制代码
Install-Package EFCore.BulkExtensions  

批量操作示例

复制代码
context.BulkInsert(entities);                   
context.BulkInsertOrUpdate(entities);           
context.BulkInsertOrUpdateOrDelete(entities);   
context.BulkUpdate(entities);                  
context.BulkDelete(entities);                  
context.BulkRead(entities);                    
context.BulkSaveChanges();    

异步版本

复制代码
context.BulkInsertAsync(entities);  
context.BulkInsertOrUpdateAsync(entities);    //Upsert  
context.BulkInsertOrUpdateOrDeleteAsync(entiti);//Sync  
context.BulkUpdateAsync(entities);  
context.BulkDeleteAsync(entities);  
context.BulkReadAsync(entities);  
context.BulkSaveChangesAsync();  

与 EF Core 使用

复制代码
// 删除  
context.Items.Where(a => a.ItemId >  500).BatchDelete();  
context.Items.Where(a => a.ItemId >  500).BatchDeleteAsync();  
  
// 更新  
context.Items.Where(a => a.ItemId <= 500).BatchUpdate(a => new Item { Quantity = a.Quantity + 100});  
context.Items.Where(a => a.ItemId <= 500).BatchUpdateAsync(a => new Item {Quantity=a.Quantity+100});  
  // can be as value '+100' or as variable '+incrementStep' (int incrementStep = 100;)  
    
// 更新  
context.Items.Where(a => a.ItemId <= 500).BatchUpdate(new Item { Description = "Updated" });  
context.Items.Where(a => a.ItemId <= 500).BatchUpdateAsync(new Item { Description = "Updated" });   
  
// Truncate  
context.Truncate<Entity>();  
context.TruncateAsync<Entity>();  

批量操作

连接字符串配置

如果使用 Windows 身份验证,则连接字符串中应包含 Trusted_Connection=True,因为 SQL 身份验证信息需要保留在连接中。

事务管理

每个批量操作默认作为单独的事务处理,并自动提交。如果需要在一个过程中执行多个操作,则应显式使用事务。

例如,由于子表不会自动与父表一起插入,因此需要显式进行第二次调用:

复制代码
using (var transaction = context.Database.BeginTransaction())
{
    context.BulkInsert(entitiesList);
    context.BulkInsert(subEntitiesList);
    transaction.Commit();
}

批量插入或更新

BulkInsertOrUpdate 方法适用于需要在同一数据库连接中执行插入或更新操作的场景。当主键(Primary Key)匹配时执行更新,否则执行插入。

批量插入、更新或删除

BulkInsertOrUpdateOrDelete 方法有效地同步表中的行与输入数据。不在输入列表中的数据库记录将被删除。

批量读取

BulkRead 方法基于一个或多个唯一列执行 SELECT 和 JOIN 操作,这些列在配置的 UpdateByProperties 中指定。

示例

复制代码
using (var transaction = context.Database.BeginTransaction())
{
    // 插入或更新主表
    context.BulkInsertOrUpdate(mainEntitiesList);
    
    // 插入或更新子表
    context.BulkInsertOrUpdate(subEntitiesList);
    
    // 提交事务
    transaction.Commit();
}

// 同步表行与输入数据
context.BulkInsertOrUpdateOrDelete(allEntitiesList);

// 根据唯一列读取数据
context.BulkRead(uniqueColumnsConfig);

性能测试结果

以下是在 SQL Server 2019 上进行的性能测试结果(单位:秒):

测试配置

硬件配置:Intel i7-10510U CPU @ 2.30GHz, DDR3 16GB, SSD Samsung 512GB

测试表结构:测试表 TestTable 包含 6 列(Guid, string x2, int, decimal?, DateTime),所有列均被插入,其中 2 列被更新

性能对比

注意事项

小数据集开销:对于较小的数据集(少于 1000 行),由于大多数批量操作需要创建临时表并在完成后删除临时表,因此会有一定的开销。

建议:建议对于大于 1000 行的数据集使用批量操作以获得最佳性能。

项目地址

https://github.com/borisdj/EFCore.BulkExtensions

总结

希望本文能为朋友们在使用EF Core开发方面带来帮助。欢迎大家在评论区留言讨论,分享您的经验和建议。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号**[DotNet技术匠]** 社区,与其他热爱技术的同行一起交流心得,共同成长!优秀是一种习惯,欢迎大家留言学习!

相关推荐
jump_jump21 小时前
Drizzle 凭什么贴着 Go 跑——从设计哲学到热路径源码
数据库·性能优化·orm
jay神21 小时前
基于SpringBoot的宠物生命周期信息管理系统
java·数据库·spring boot·后端·web开发·宠物·管理系统
秋921 小时前
MySQL 8.0.46 与 MySQL 9.7.0在sql语句方面的区别并举例说明
数据库·sql·mysql
一只数据集21 小时前
NVIDIA Nemotron AIQ Agentic Safety Dataset:面向企业级智能体系统的安全与防护评估数据集全面解析
网络·数据库·安全
Amazinqc21 小时前
Mysql数据库数据软隔离的并发死锁情况
数据库·mysql·死锁
DianSan_ERP21 小时前
京东订单接口集成中如何处理消费者敏感信息的安全与合规问题?
前端·数据库·后端·团队开发·运维开发
原来是猿21 小时前
TCP Echo Server 深度解析:从单进程到线程池的演进之路(中)
linux·服务器·数据库
treesforest21 小时前
IP地址段查询完全指南:从单IP查到IPv4段批量归属地查询
网络·数据库·网络协议·tcp/ip·网络安全·运维开发
渣渣灰95871 天前
基于STM32F03ZET6移植FreeRTOS
数据库·stm32·嵌入式硬件
庞轩px1 天前
第七篇:Redis分布式锁——从setnx到RedLock的演进之路
数据库·redis·分布式锁·redission·setnx·redlock·可重入锁