简体   繁体   English

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

[英]Why is inserting entities in EF 4.1 so slow compared to ObjectContext?

Basically, I insert 35000 objects within one transaction:基本上,我在一个事务中插入 35000 个对象:

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

This takes forever!这需要永远! If I use the underlying ObjectContex t (by using IObjectAdapter ), it's still slow but takes around 20s.如果我使用底层ObjectContex t(通过使用IObjectAdapter ),它仍然很慢,但需要大约 20 IObjectAdapter It looks like DbSet<> is doing some linear searches, which takes square amount of time...看起来DbSet<>正在做一些线性搜索,这需要平方的时间......

Anyone else seeing this problem?还有其他人看到这个问题吗?

As already indicated by Ladislav in the comment, you need to disable automatic change detection to improve performance:正如 Ladislav 在评论中已经指出的那样,您需要禁用自动更改检测以提高性能:

context.Configuration.AutoDetectChangesEnabled = false;

This change detection is enabled by default in the DbContext API.默认情况下,在DbContext API 中启用此更改检测。

The reason why DbContext behaves so different from the ObjectContext API is that many more functions of the DbContext API will call DetectChanges internally than functions of the ObjectContext API when automatic change detection is enabled. DbContext行为与ObjectContext API 如此不同的原因是,当启用自动更改检测时, DbContext API 的更多函数将在内部调用DetectChanges不是ObjectContext API 的函数。

Here you can find a list of those functions which call DetectChanges by default. 在这里您可以找到默认调用DetectChanges的那些函数的列表。 They are:他们是:

  • The Add , Attach , Find , Local , or Remove members on DbSet DbSet上的AddAttachFindLocalRemove成员
  • The GetValidationErrors , Entry , or SaveChanges members on DbContextGetValidationErrorsEntry ,或SaveChanges上成员DbContext
  • The Entries method on DbChangeTracker DbChangeTracker上的Entries方法

Especially Add calls DetectChanges which is responsible for the poor performance you experienced.尤其是Add调用DetectChanges ,这会导致您遇到的性能不佳。

I contrast to this the ObjectContext API calls DetectChanges only automatically in SaveChanges but not in AddObject and the other corresponding methods mentioned above.与此相反, ObjectContext API 仅在SaveChanges自动调用DetectChanges ,而不在AddObject和上述其他相应方法中调用。 That's the reason why the default performance of ObjectContext is faster.这就是ObjectContext默认性能更快的原因。

Why did they introduce this default automatic change detection in DbContext in so many functions?为什么他们在这么多函数中引入了这种默认的DbContext自动变化检测? I am not sure, but it seems that disabling it and calling DetectChanges manually at the proper points is considered as advanced and can easily introduce subtle bugs into your application so use [it] with care .我不确定,但似乎禁用它并在适当的点手动调用DetectChanges被认为是高级的,并且很容易将细微的错误引入您的应用程序,因此请谨慎使用 [it]

Little empiric test with EF 4.3 CodeFirst:使用 EF 4.3 CodeFirst 的小经验测试:

Removed 1000 objects with AutoDetectChanges = true : 23 sec使用 AutoDetectChanges = true 删除了 1000 个对象:23 秒

Removed 1000 objects with AutoDetectChanges = false: 11 sec使用 AutoDetectChanges = false: 11 sec 删除了 1000 个对象

Inserted 1000 objects with AutoDetectChanges = true : 21 sec使用 AutoDetectChanges = true 插入 1000 个对象:21 秒

Inserted 1000 objects with AutoDetectChanges = false : 13 sec使用 AutoDetectChanges = false 插入 1000 个对象:13 秒

在 .netcore 2.0 中,这被移至:

context.ChangeTracker.AutoDetectChangesEnabled = false;

Besides the answers you have found here.除了你在这里找到的答案。 It is important to know that at the database level is is more work to insert than it is to add.重要的是要知道在数据库级别插入比添加更多的工作。 The database has to extend/allocate new space.数据库必须扩展/分配新空间。 Then it has to update at least the primary key index.然后它必须至少更新主键索引。 Although indexes may also be updated when updating, it is a lot less common.虽然更新时索引也可能会被更新,但这种情况要少得多。 If there are any foreign keys it has to read those indexes as well to make sure referential integrity is maintained.如果有任何外键,它也必须读取这些索引以确保保持参照完整性。 Triggers can also play a role although those can affect updates the same way.触发器也可以发挥作用,尽管它们可以以相同的方式影响更新。

All that database work makes sense in daily insert activity originated by user entries.所有这些数据库工作在由用户条目发起的日常插入活动中都是有意义的。 But if you are just uploading an existing database, or have a process that generates a lot of inserts.但是如果你只是上传一个现有的数据库,或者有一个生成大量插入的过程。 You may want to look at ways of speeding that up, by postponing it to the end.您可能想通过将其推迟到最后来查看加快速度的方法。 Normally disabling indexes while inserting is a common way.通常在插入时禁用索引是一种常见的方法。 There is very complex optimizations that can be done depending on the case, they can be a bit overwhelming.可以根据情况进行非常复杂的优化,它们可能有点令人难以抗拒。

Just know that in general insert will take longer than updates.只知道通常插入比更新需要更长的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 与PrincipalSearcher相比,为什么DirectorySearcher这么慢? - Why is DirectorySearcher so slow when compared to PrincipalSearcher? 为什么与.net相比,java中的递归这么慢? - Why recursion in java is so slow compared to .net? 将复合poco映射到EF objectcontext实体 - Mapping composite poco to EF objectcontext entities 与LINQ相比,为什么Array.Sort()这么慢? - Why is Array.Sort() so slow compared to LINQ? 为什么EF为我未指定的实体插入新数据? - Why is EF inserting new data for entities that I'm not specifying? 使用EF4 POCO将实体附加到ObjectContext而没有相关实体 - Attaching entity to ObjectContext without related entities with EF4 POCO 如何在Entities ObjectContext上设置EF Trace而不传入连接名称 - How to setup EF Trace on an Entities ObjectContext without passing in the connection name 非EF实体的“ ObjectContext实例已被处置” - “The ObjectContext instance has been disposed” for non-EF entities 如何使用POCO和自定义ObjectContext正确更新EF4中的实体? - How to correctly update entities in EF4 using POCO and custom ObjectContext? 带有Entity Framework 6的ObjectContext在现有相关实体上插入重复项 - ObjectContext with Entity Framework 6 inserting duplicates on existing related entities
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM