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

Har*_*mut 79 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();
}
Run Code Online (Sandbox Code Playgroud)

这需要永远!如果我使用底层ObjectContext(通过使用IObjectAdapter),它仍然很慢但需要大约20秒.它似乎DbSet<>正在进行一些线性搜索,这需要花费大量时间......

其他人看到这个问题?

Sla*_*uma 125

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

context.Configuration.AutoDetectChangesEnabled = false;
Run Code Online (Sandbox Code Playgroud)

默认情况下,DbContextAPI中会启用此更改检测.

DbContextObjectContextAPI 行为如此不同的原因是,当启用自动更改检测时,DbContextAPI的许多其他功能将在DetectChanges内部调用,而不是ObjectContextAPI的函数.

在这里,您可以找到DetectChanges默认调用的函数列表.他们是:

  • Add,Attach,Find,Local,或Remove成员DbSet
  • GetValidationErrors,EntrySaveChanges成员DbContext
  • Entries对方法DbChangeTracker

特别是对你所经历的糟糕表现负责的Add电话DetectChanges.

与此形成对比的是,ObjectContextAPI DetectChanges仅自动调用SaveChanges但不在AddObject上面提到的其他相应方法中.这就是为什么默认性能ObjectContext更快的原因.

为什么他们DbContext在如此多的功能中引入了这种默认的自动变化检测?我不确定,但似乎禁用它并DetectChanges在适当的位置手动调用被认为是高级的,并且可以轻松地在您的应用程序中引入细微的错误,因此请谨慎使用[it].

  • @Hartmut:您可以在派生的DbContext的构造函数内禁用更改检测,然后始终禁用它.但就个人而言,这个关于"潜在地引入细微错误"的评论让我感到紧张.我默认情况下会更改检测,并且仅在像你这样的代码块中禁用它,在那里性能提升很明显,我觉得它不会导致问题. (3认同)

Zax*_*Zax 11

使用EF 4.3 CodeFirst进行的经验测试很少:

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

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

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

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


Max*_*xvt 10

在 .netcore 2.0 中,这被移至:

context.ChangeTracker.AutoDetectChangesEnabled = false;