添加和删​​除时DbContext很慢

     2023-02-16     133

关键词:

【中文标题】添加和删​​除时DbContext很慢【英文标题】:DbContext is very slow when adding and deleting 【发布时间】:2012-04-23 14:28:09 【问题描述】:

在数据库优先的场景中使用 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

我尝试在 VC 2010 中使用 EF 4.3,在 VS 11 中使用 EF 5.0 Beta 2,结果几乎相同。我使用了“EF 4.x POCO Entity Generator for C#”、“EF 4.x DbContext Generator for C#”和“EF 5.x DbContext Generator for C#”提供的 T4 模板。

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

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

感谢任何想法/更正。

【问题讨论】:

除拉迪斯拉夫回答外的两个参考:***.com/questions/5943394/… 和 ***.com/questions/5940225/… 【参考方案1】:

在 EF6 中,您现在可以在 DbSet 上使用 AddRange 和 RemoveRange。

从链接到文档:

请注意,如果 AutoDetectChangesEnabled 设置为 true(这是默认设置),则 DetectChanges 将在 adding,deleting 任何实体之前调用一次,并且不会再次调用。这意味着在某些情况下,Add,RemoveRange 的性能可能比多次调用 Add,Remove 好得多。

【讨论】:

【参考方案2】:

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

dbContext.Configuration.AutoDetectChangesEnabled = false;

// Now do all your changes

dbContext.ChangeTracker.DetectChanges();
dbContext.SaveChanges();

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

DbContext API 中有一些架构更改,每次您 AddAttachDelete 从上下文中检查任何内容时都会检查实体的更改。在 ObjectContext API 中,此检测仅在您触发 SaveChanges 时运行。它是大多数常见场景的更好解决方案,但它需要对海量数据处理进行特殊处理。

【讨论】:

谢谢拉迪斯拉夫。这确实是在添加/删除许多实体并在最后保存更改时导致性能问题的原因。将 AutoDetectChangesEnabled 设置为 false 后,结果与 ObjectContext 几乎相同。但与 ObjectContext 相比,单次插入,尤其是单次删除后跟 SaveChanges 的速度仍然较慢,即使我将 AutoDetectChangesEnabled 设置为 false 并在 SaveChanges 之前调用 DetectChanges。使用 DbContext 时,删除 2000 个实体仍然需要大约 17 秒 ...使用 ObjectContext 时只用了大约 2.1 秒。我认为这只是因为更改跟踪中的这些更改。顺便问一下:您能否解释一下为什么每次添加、附加或删除时检查更改对于大多数常见场景来说是更好的解决方案? @JürgenBayer:我已经复制了您在评论中描述的 DeleteObject/Remove 的巨大性能差异。如果您从代码中删除DetectChanges,差异就会消失(如果您只添加和删除实体,则实际上不需要)。但尽管如此,我的理解是ObjectContext.SaveChanges() 在内部调用DetectChanges,而DbContext.SaveChanges()AutoDetectChanges 被禁用时不会。因此,调用 DetectChanges + DbContext.SaveChanges()(禁用 AutoDetectChanges)应该与调用 ObjectContext.SaveChanges() 相同 - 理论上。 AddRemove 的不同行为也令人惊讶。您能否创建一个专门针对这一点的新问题(在每个DeleteObject/Remove 之后调用SaveChanges)?那时这个话题会得到更多的关注。在循环中调用SaveChanges 通常是个坏主意,但问题仍然是为什么在这种特殊情况下ObjectContext 的执行速度比DbContext 快得多。 这对我的表现产生了巨大的影响。添加 100 个实体大约需要 102,000 毫秒。通过关闭AutoDetectChangesEnabled,它降至约 5,000 毫秒。太棒了!

sql添加和删​​除外键(代码片段)

查看详情

text添加和删​​除类选择行(代码片段)

查看详情

添加和删​​除视图时出现问题

】添加和删​​除视图时出现问题【英文标题】:Problemtabbingtofieldwhenaddingandremovingview【发布时间】:2011-05-3002:33:02【问题描述】:我有一个包含NSSearchField的范围栏。可以使用菜单项显示和隐藏该栏。我通过创建一个新的NSViewCont... 查看详情

actionscript3添加和删​​除到数组(代码片段)

查看详情

添加和删​​除 UIStackViews 弄乱了我的 UIScrollView

】添加和删​​除UIStackViews弄乱了我的UIScrollView【英文标题】:AddingandremovingUIStackViewsmessingupmyUIScrollView【发布时间】:2018-09-1119:31:12【问题描述】:每当我使用pickerview将视图从AutoRent切换到ScheduleRent时,它都能完美运行。当我... 查看详情

添加和删​​除对表格进行排序的元素类

】添加和删​​除对表格进行排序的元素类【英文标题】:Addingandremovinganelementclassthatsortsatable【发布时间】:2022-01-1722:16:22【问题描述】:我有一张可以通过图标排序的表格图标按升序和降序排列下面的代码是通过inspectelements... 查看详情

添加和删​​除文件以不完全重写文件的最有效方法是啥?

】添加和删​​除文件以不完全重写文件的最有效方法是啥?【英文标题】:Whatisthemosteffecientwayofaddingandremovingpiecesoffiletonotrewriteitfully?添加和删​​除文件以不完全重写文件的最有效方法是什么?【发布时间】:2013-09-1215:10:51... 查看详情

sql添加和删​​除postgresjsonb子键特有的元素:简短set实现(代码片段)

查看详情

powershell添加和删​​除windows存储来自powershell/cmd的应用程序(代码片段)

查看详情

ef首次加载很慢(代码片段)

1.CodeFirst第一次启动会对比程序中的Model与数据库表(databaseinitializer),生成Model与数据库的映射视图。使用ef6的情况下,在Application_Start里面添加using(vardbcontext=newNCContext())varobjectContext=((IObjectContextAdapter)dbcontext).ObjectCon 查看详情

如何使用 Dbcontext 添加条目

】如何使用Dbcontext添加条目【英文标题】:HowtoaddanentryusingDbcontext【发布时间】:2021-09-1805:49:38【问题描述】:我在pgAdmin4中有一个表,我试图仅将数据添加到hours和total_amount列而不更改任何其他数据。其他数据被添加到不同的页... 查看详情

EntityFramework 4.1 DbContext 选择添加带有附加字符的 CAST 列

】EntityFramework4.1DbContext选择添加带有附加字符的CAST列【英文标题】:EntityFramework4.1DbContextselectaddingCASTcolumnswithadditionalcharacters【发布时间】:2013-09-2314:59:44【问题描述】:我正在从dbcontext执行标准GetAll():DbContext.Set<T>()但是... 查看详情

将 DbContext 添加到现有的 .net 4 应用程序中

】将DbContext添加到现有的.net4应用程序中【英文标题】:AddingDbContextintoexisting.net4application【发布时间】:2013-06-3010:58:16【问题描述】:我有基于对象上下文的现有.net4应用程序。现在我通过继承DbContext并调用构造函数方法并传递... 查看详情

codefirst中dbcontext动态添加dbset

usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Data.Entity;usingSystem.ComponentModel.DataAnnotations;usingSystem.Data.Entity.ModelConfiguration;usingSystem. 查看详情

.netcore下使用多个dbcontext(代码片段)

 一个项目中使用多个DbContext或者种数据库的多个DbContext业务需要单个DbContext使用不需要给出说明1、dotnetefmigrationsaddmigrationname2、dotnetefdatabaseupdate多个DbContext请使用如下命令指定dbcontext名称或者指定生成到目录1、添加为dbconte... 查看详情

除了 dbContext 之外,如何向 Blazor 中的服务添加参数?

】除了dbContext之外,如何向Blazor中的服务添加参数?【英文标题】:HowtoaddaparametertoaserviceinBlazorinadditiontothedbContext?【发布时间】:2022-01-1000:39:43【问题描述】:VS2022NetCore6EF6builder.Services.AddDbContext<MyAppDbContext>(optionsremovedfors 查看详情

Asp.Net Core:向 IdentityDbContext 添加数据或使用 DbContext

】Asp.NetCore:向IdentityDbContext添加数据或使用DbContext【英文标题】:Asp.NetCore:AdddatatoIdentityDbContextoruseDbContext【发布时间】:2018-10-2621:51:43【问题描述】:我使用Asp.NetCoreWebApi项目。我可以将我的表添加到IdentityDbContext,如下所示:... 查看详情

EF Core 为 dbContext 传递 TEntity 以执行更新或添加

】EFCore为dbContext传递TEntity以执行更新或添加【英文标题】:EFCorepassTEntityfordbContexttodoUpdateorAdd【发布时间】:2021-08-0610:17:11【问题描述】:使用EFCore,我有10种方法基本上做同样的事情。更新或添加,然后SaveChanges()即publicvoidUpdat... 查看详情