添加和删​​除时DbContext非常慢

Jür*_*yer 46 entity-framework dbcontext

在数据库优先的场景中使用DbContext时,我发现与ObjectContext相比,添加和删除实体的速度非常慢.如果添加2000个实体并在最后保存更改,DbContext比ObjectContext慢3到5倍(顺便说一句:我知道使用SqlBulkCopy添加大量实体会更好,但这不是重点).如果在每次添加后保存更改,DbContext仍然慢近两倍.当涉及删除时,它甚至变得更糟:当在所有实体删除结束时保存时,DbContext比ObjectContext慢大约18倍.

我使用了我用来比较数据库访问技术和小型控制台应用程序的高度开发的测试应用程序来进行双重检查.两者都显示使用DbContext添加和删除实体的结果不佳.以下是控制台应用程序的结果:

Inserting 2000 entities via DbContext saving changes at the end: 2164ms
Inserting 2000 entities via ObjectContext saving changes at the end: 457ms
Inserting 2000 entities via DbContext saving changes after each object addition: 8420ms
Inserting 2000 entities via ObjectContext saving changes after each object adding: 4857ms
Inserting 2000 entities via DbContext using a new DbContext for each object addition: 4018ms
Deleting 2000 entities via DbContext saving changes at the end: 4794ms
Deleting 2000 entities via ObjectContext saving changes at the end: 261ms
Deleting 2000 entities via DbContext saving changes after each object deletion: 25536ms
Deleting 2000 entities via ObjectContext saving changes after each object deletion: 2110ms
Run Code Online (Sandbox Code Playgroud)

我尝试在VC 2010中使用EF 4.3,在VS 11中使用EF 5.0 Beta 2,结果几乎相同.我使用了"用于C#的EF 4.x POCO实体生成器","用于C#的EF 4.x DbContext生成器"和"用于C#的EF 5.x DbContext生成器"提供的T4模板.

可能有什么不对?根据测试结果,我永远不会在必须添加或删除实体的应用程序中使用DbContext(不幸的是,DbContext对我来说无法使用).

我将控制台测试应用程序放在我的Web服务器上:EF 4.3 DbContext Test,EF 5.0 DbContext Test

任何想法/更正都表示赞赏.

Lad*_*nka 92

尝试将此添加到您的DbContext测试:

dbContext.Configuration.AutoDetectChangesEnabled = false;

// Now do all your changes

dbContext.ChangeTracker.DetectChanges();
dbContext.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

并尝试再次运行您的测试.

有在的DbContext API一些结构的变化,其每一次检查中实体的变化你Add,AttachDelete任何从上下文.在ObjectContext API中,此检测仅在您触发时运行SaveChanges.对于大多数常见场景而言,它是更好的解决方案,但它需要特殊处理海量数据处理

  • @JürgenBayer:我再现了你在评论中描述的"DeleteObject/Remove"的巨大性能差异.如果从代码中删除"DetectChanges",则差异消失(如果只添加和删除实体,则实际上不需要).但是我的理解是`ObjectContext.SaveChanges()`在内部调用`DetectChanges`,而'DbContext.SaveChanges()`在禁用'AutoDetectChanges`时不会.因此,在理论上,调用`DetectChanges` +`DbContext.SaveChanges()`(禁用AutoDetectChanges)应该与调用`ObjectContext.SaveChanges()`相同. (3认同)
  • 这对我的表现产生了巨大的影响.要添加100个实体,它大约需要102,000毫秒.通过关闭`AutoDetectChangesEnabled`,它降至~5,000毫秒.真棒! (3认同)

And*_*erg 14

EF6中,您现在可以在DbSet上使用AddRangeRemoveRange.

从链接上的文档:

请注意,如果将AutoDetectChangesEnabled设置为true(这是默认值),则在{添加,删除}任何实体之前将调用一次DetectChanges,并且不会再次调用.这意味着在某些情况下{添加,删除}范围可能比多次调用{添加,删除}要好得多.