实体框架大容量插入-创建大量对象/实体是缓慢的部分
本文关键字:实体 缓慢 对象 大容量 框架 插入 创建 | 更新日期: 2024-09-22 08:41:05
这里和其他地方有很多关于如何使用EF加速批量插入的信息和答案。
然而,我只插入了大约10000条记录和创建实体的缓慢部分。
首先,我将外部数据保存到一个数据表中,然后循环并为每一行创建一个新的entity
,在循环中添加子实体(来源于其他几个数据表),循环完成后调用db.SaveChanges()
。
在我最初的评测中,db.SaveChanges()
速度很慢,但与首先创建所有对象的循环相比没有什么不同——要么作为单独的List<entity> entities
,要么直接创建到上下文。
这是常有的事吗?在我所看到的大容量插入的所有问题中,大多数似乎与数据库的最终提交有关。
编辑以添加一些代码请原谅psudo代码
DataTable ref1 = ConvertCSVtoDataTable(csv, firstRowsToDelete: 15); // Return's a Datatable from a CSV
foreach(string file in ListOfFilesToProcess)
{
DataTable tbl = loadExcelFiles(file);
foreach(DataRow dr in tbl.Rows)
{
Entity newEntity = new Entity();
Entity.property1 = dr["Property1"].ToString();
... // Keep mapping properties to elements in the datatable
Entity.Child.Add(new ChildEntity() { prop1 = ref1["ChildProp1"].ToString() });
// Add the newly created entity to the context
db.Entity.Add(newEntity);
}
}
// Save the context
db.SaveChanges();
因此,从保存上下文的角度来看,有几千个newEntity
对象及其子navigation
对象。
遍历数据表并创建所有这些对象是最慢的部分!
此外,已经设置了db.Configuration.AutoDetectChangesEnabled = false;
。
"创建所有对象"部分的缓慢部分是检测更改。
您应该始终使用AddRange而不是Add
- 添加:检测每个对象的更改
- AddRange:只检测一次更改(添加所有对象后)
此代码应修复创建对象时速度较慢的部分:
DataTable ref1 = ConvertCSVtoDataTable(csv, firstRowsToDelete: 15); // Return's a Datatable from a CSV
List<Entity> list = new List<Entity>();
foreach(string file in ListOfFilesToProcess)
{
DataTable tbl = loadExcelFiles(file);
foreach(DataRow dr in tbl.Rows)
{
Entity newEntity = new Entity();
Entity.property1 = dr["Property1"].ToString();
... // Keep mapping properties to elements in the datatable
Entity.Child.Add(new ChildEntity() { prop1 = ref1["ChildProp1"].ToString() });
list.Add(newEntity);
}
}
// Add all newly created entities to the context
db.Entity.AddRange(list);
// Save the context
db.SaveChanges();
如果在此修复之后,您仍然有一些性能问题(这次来自数据库),您应该尝试BulkSaveChanges/BulkInsert第三方库。
这里有一篇关于这些库的文章:实体框架-批量插入库评论&比较。
- 实体框架扩展(推荐,支持一切)
- EntityFramework。隔板插入件
- EntityFramework。公用设施
免责声明:我是项目实体框架扩展
只需使用大容量插入即可。即使你已经克服了EF糟糕得离谱的表现,你仍然必须面对数据库不喜欢单个插入的问题。