EF Core 大规模导入核心是避免加载实体、禁用追踪、减少 SQL 生成;EF Core 9 的 ExecuteInsert 支持免跟踪批量插入,AddRange+配置优化适用于需实体逻辑场景,BulkExtensions 适合十万级以上及需主键回填,超百万级推荐原生 SqlBulkCopy 或 COPY。

EF Core 处理大规模数据导入,核心不是“怎么加”,而是“怎么不加”——避免把实体加载进内存、不触发变更追踪、不逐条生成 SQL。EF Core 9 起已原生支持高效批量操作,配合合理配置,万级数据导入可控制在秒级。
用 ExecuteInsert 做真正免跟踪的批量插入
EF Core 9 引入 ExecuteInsert,是首个真正跳过上下文跟踪、直接生成 INSERT ... VALUES (...), (...) 的原生 API。它不创建实体实例,不走 ChangeTracker,也不调用 SaveChanges。
- 适合从原始数据(如 CSV 行、DTO 列表)直接写入,无需映射为完整实体类
- 语法简洁:
context.Products.ExecuteInsert(productDtos.Select(d => new Product { Name = d.Name, Price = d.Price })); - 自动分批(默认 batch size=1000),适配 SQL Server / PostgreSQL 等对单语句参数数量的限制
- 不支持自增主键回填,如需 ID 返回,改用 BulkExtensions 或 SqlBulkCopy
用 AddRange + SaveChanges 配合禁用追踪
若必须使用实体对象(比如要触发构造逻辑或验证),AddRange + SaveChanges 是兼容性最好的方案,但需关闭开销项:
- 关自动变更检测:
context.ChangeTracker.AutoDetectChangesEnabled = false; - 关保存前验证:
context.Configuration.ValidateOnSaveEnabled = false; - 手动设状态(可选):
context.Entry(entity).State = EntityState.Added;,跳过 DetectChanges - 建议搭配
UseBatchSize(500)(在 DbContextOptions 中配置),避免单次 SQL 过长
第三方库:EFCore.BulkExtensions 最稳的工业选择
当数据量超 10 万、需事务一致性、或要求主键回填/冲突处理(ON CONFLICT / MERGE),EFCore.BulkExtensions 仍是生产首选:
- 底层调用 SqlBulkCopy(SQL Server)、COPY(PostgreSQL)、REPLACE INTO(MySQL),接近原生速度
- 支持 Upsert(BulkInsertOrUpdate)、批量更新字段、条件删除等全场景
- 示例:
context.BulkInsert(entities, opt => { opt.BatchSize = 2000; opt.TrackGraph = false; }); - 注意:需 NuGet 安装,且不同数据库驱动版本需匹配(如 v8.x 支持 EF Core 8/9)
绕过 ORM:原生 SQL + SqlBulkCopy(极限场景)
百万级以上导入、ETL 类任务,或需极致可控性时,直接放弃 EF Core 的抽象层:
- SQL Server:用
SqlBulkCopy写 DataTable 或 IDataReader,吞吐可达 5–10 万行/秒 - PostgreSQL:用
NpgsqlConnection.BeginTextImport或 COPY FROM STDIN - EF Core 可配合:
context.Database.GetDbConnection()获取原生连接复用 - 缺点:丢失模型验证、关系映射、迁移约束检查,需自行保障数据一致性
基本上就这些。选型看三点:数据量级、是否要 ID 回填、团队对 ORM 抽象的依赖程度。小批量(500k)直连原生更靠谱。










