将对象添加到实体框架上下文大约需要 1.5 秒
Posted
技术标签:
【中文标题】将对象添加到实体框架上下文大约需要 1.5 秒【英文标题】:Adding an object to the entity framework context takes about 1.5 seconds 【发布时间】:2013-08-29 09:33:21 【问题描述】:我正在寻找可能的原因或可以加快速度的方法。
我本质上是用这样的代码构造一个对象
(伪代码)
Person p = new Person();
Address a = new Address() ... properties set here ... ;
Employer e = new Employer() ... properties set here ... ;
// etc.
p.Employer = e;
p.Address = a;
//etc.
最后:
_context.Person.Add(p);
当我分析代码时,人的构造需要 0 毫秒,这简直是闪电般的速度。但是,当我将人添加到上下文中时,大约需要 1500 毫秒。可能与约束检查有关吗?数据库非常大,虽然它没有加载到内存或其他任何东西中,所以在它执行Add
时它不应该触及数据库。
只有当我写_context.SaveChanges()
时才应该写。
有什么提高速度的建议吗?
编辑:基准测试是这样完成的:(sw 是 new Stopwatch()
)
sw.Restart();
context.Person.Add(p);
Console.WriteLine("Person added to context: " + sw.ElapsedMilliseconds + "ms");
编辑 2:情节变厚了。
当我加载大量人员并将他们添加到数据库中时,我要做的第一个操作是查看该人是否已经存在于数据库中。出于速度原因,我将 Person.PersonId 的完整列表提取到哈希表中,并检查它们是否有要插入的每条记录。
如果此人已存在于列表中,我将其从数据库中拉出。这大约需要 5 毫秒,而且我不对数据做任何事情(因为我还没有写那部分),然后直接跳到下一个。
但是,当它到达正在添加到上下文中的新条目时,正是该行导致了大幅减速。代码如下:
matchPerson = _context.Person.SingleOrDefault(c => c.PersonId == intPersonId);
因此,如果他们已经在数据库中,它会通过 0ms 哈希表检查将人从数据库中拉出(这是即时的)。
大约需要 5 毫秒。
如果我在这条线出现时执行上述_context.Add
,它会变得非常慢。如果我将其注释掉,大约需要 40 毫秒,并且每增加一条记录就会增加(因此在 2,000 条记录之后大约需要 200 毫秒)。
我看不到这两行之间的链接,所以上下文查询可能会重置上下文的状态并减慢下一个操作的速度?
【问题讨论】:
1500 毫秒太多了,即使它是在 db 中写入。您确定您的基准测试是正确的(或者没有其他任何操作涉及)? 我想是的,我只是在那条线上放了一个秒表。我已经在问题中添加了代码。 您是否在 IDE 中执行测试?您是否编译为发布模式或调试模式?请参阅 here 了解常见的基准测试错误。 是的,它正在调试中,我会尝试在发布模式下编译它,但我不会认为它会产生足够的差异,因为我不想减少毫秒数。我会尽快通知你... 实体是否特别大/复杂?可能与自动更改检测(***.com/questions/5943394/…)有关,尽管从您所说的 =o 看来不太可能。 Ohlin 的好点子,这是在每次添加时发生,还是第一次发生? 【参考方案1】:根据 cmets 的要求(如果没有关闭副本),减速与自动更改检测有关,DbContext
API 中默认启用。
禁用自动更改检测:
context.Configuration.AutoDetectChangesEnabled = false;
可以在这个公认的答案中找到更完整/完整的描述(我当然不能在这里更好):
Why is inserting entities in EF 4.1 so slow compared to ObjectContext?
【讨论】:
谢谢。这是即时的。我仍然很想知道为什么在保存更改之间对上下文进行查询会产生如此大的性能成本。 我不确定该答案的 cmets 中的第一个链接 (***.com/questions/5917478/…) 是否能揭示任何额外的亮点(与拍摄对象快照的实际过程有关,并带有一些基准)。以上是关于将对象添加到实体框架上下文大约需要 1.5 秒的主要内容,如果未能解决你的问题,请参考以下文章