实体框架大容量插入-创建大量对象/实体是缓慢的部分

本文关键字:实体 缓慢 对象 大容量 框架 插入 创建 | 更新日期: 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糟糕得离谱的表现,你仍然必须面对数据库不喜欢单个插入的问题。