YMC*_*YMC 33 performance entity-framework poco entity-framework-4.1
8个月前在这里讨论了同样的话题:如何加速DbSet.Add()?.除了使用我们不接受的SqlBulkCopy之外,没有提出任何解决方案.我决定再次提出这个问题,希望围绕这个问题有新的想法和想法,并提出其他解决方法.至少我只是好奇为什么这个操作需要很长时间才能运行.
好吧,问题是:我必须将30K实体更新到数据库(EF 4.1,POCO).实体类型非常简单,包含整数Id +其他4个整数属性,与其他类型无关.2例:
所有这些都是新记录.每个实体逐个运行context.Entities.Add(entity)需要90秒,Cntx.Configuration.AutoDetectChangesEnabled = false(true值使其永久运行).然后SaveChanges只需要一秒钟.其他方法:将它附加到像这样的上下文需要相同的90秒:
Cntx.Entities.Attach(entity);
Cntx.Entry(entity).State = EntityState.Added;
Run Code Online (Sandbox Code Playgroud)它们都是现有的记录,有一些变化.在这种情况下,将它附加到现有数据上下文只需几毫秒,如下所示:
Cntx.Entities.Attach(entity);
Cntx.Entry(entity).State = EntityState.Modified;
Run Code Online (Sandbox Code Playgroud)
看到不同?
Add方法背后的原因是什么让它的工作速度非常慢?
YMC*_*YMC 27
我有一些有趣的性能测试结果,我找到了一个罪魁祸首.在我读过的任何EF源代码中,我都没有看到任何类似的信息.
事实证明,在基类中重写了Equals.基类应该包含在所有类型的具体实体之间共享的Id属性.许多EF书籍推荐这种方法并且非常清楚.您可以在此处找到它,例如:如何最好地实现自定义类型的等于?
更确切地说,性能被取消装箱操作(具体类型转换的对象)所杀死,使其工作得如此之慢.当我评论这行代码时,它需要3秒才能反对90秒!
public override bool Equals ( object obj )
{
// This line of code made the code so slow
var entityBase = obj as EntityBase;
...
}
Run Code Online (Sandbox Code Playgroud)
当我发现它时,我开始考虑可能是这个Equals的替代品.第一个想法是为EntityBase实现IEquatable,但它根本没有运行.所以我最终决定要为我的模型中的每个具体实体类实现IEquatable.我只有少数,所以这对我来说是一个小小的更新.您可以将整个Equal操作功能(通常是2对象ID比较)放入扩展方法,以在具体实体类之间共享并运行它:Equal((EntityBase)ConcreteEntityClass).最有趣的是,这个IEquatable加速了EntitySet.Add 6次!
所以我没有更多的性能问题,相同的代码运行时间不到一秒钟.我获得了180倍的性能提升!惊人!
结论: