与ObjectContext相比,为什么在EF 4.1中插入实体的速度如此之慢?

时间:2011-05-09 22:52:41

标签: c# entity-framework entity-framework-4.1

基本上,我在一个事务中插入35000个对象:

using(var uow = new MyContext()){
  for(int i = 1; i < 35000; i++) {
     var o = new MyObject()...;
     uow.MySet.Add(o);
  }
  uow.SaveChanges();
}

这需要永远! 如果我使用基础ObjectContex t(使用IObjectAdapter),它仍然很慢但需要大约20秒。看起来DbSet<>正在进行一些线性搜索,这需要花费大量时间......

其他人都看到了这个问题?

4 个答案:

答案 0 :(得分:124)

正如Ladislav在评论中已经指出的那样,您需要禁用自动更改检测以提高性能:

context.Configuration.AutoDetectChangesEnabled = false;

默认情况下,DbContext API会启用此更改检测。

DbContextObjectContext API的行为如此不同的原因是DbContext API的更多功能将在内部调用DetectChanges而不是{{1}的函数启用自动更改检测时的API。

Here您可以找到默认调用ObjectContext的函数列表。他们是:

  • DetectChanges上的AddAttachFindLocalRemove成员
  • DbSet上的GetValidationErrorsEntrySaveChanges成员
  • DbContext
  • 上的Entries方法

尤其是DbChangeTracker来电Add,这会导致您遇到的糟糕表现。

我将DetectChanges API调用ObjectContext仅与DetectChanges中的SaveChanges进行对比,而不是AddObject和上面提到的其他相应方法。这就是ObjectContext默认效果更快的原因。

为什么他们在DbContext这么多功能中引入了这个默认的自动更改检测?我不确定,但似乎禁用它并在适当的位置手动调用DetectChanges被视为advanced and can easily introduce subtle bugs into your application so use [it] with care

答案 1 :(得分:11)

使用EF 4.3 CodeFirst进行小经验测试:

使用AutoDetectChanges = true删除了1000个对象:23秒

使用AutoDetectChanges = false删除了1000个对象:11秒

使用AutoDetectChanges = true插入1000个对象:21秒

使用AutoDetectChanges = false插入1000个对象:13秒

答案 2 :(得分:4)

在.netcore 2.0中,这已移至:

<?php require('db_connect.php'); if($_POST['empid']) { $sql = "DELETE FROM comments WHERE id='".$_POST['empid']."'"; if($sql) { echo "Record Deleted"; } } ?>

答案 3 :(得分:1)

除了你在这里找到的答案。重要的是要知道在数据库级别插入的工作量要多于添加的工作量。数据库必须扩展/分配新空间。然后它必须至少更新主键索引。尽管在更新时也可能会更新索引,但这种情况并不常见。如果有任何外键,它必须读取这些索引以确保保持参照完整性。触发器也可以起作用,尽管它们可以以相同的方式影响更新。

所有数据库工作在由用户条目引发的每日插入活动中都有意义。但是,如果您只是上传现有数据库,或者有一个生成大量插入的流程。您可能希望通过将其推迟到最后来寻找加速这种方法的方法。通常在插入时禁用索引是一种常见方式。根据具体情况,可以进行非常复杂的优化,它们可能有点压倒性。

只要知道插件通常需要的时间比更新时间长。