为什么DbSet.Add工作得如此之慢?

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倍的性能提升!惊人!

结论:

  1. 运行EntitySet.Add的最快方法是为特定实体提供IEquatable(0.5秒)
  2. 缺少IEquatable使其运行3秒.
  3. 拥有Equals(object obj),大多数消息来源推荐它使它运行90秒

  • @YMC:你能详细说明如何实现`IEquatable <T>`?我很困惑是否为了一个可变类型覆盖object.Equals()(因为你当然也应该覆盖object.GetHashCode(),但是如果哈希代码在对象在字典中时发生变化,它就会变成孤立的).在持久化对象之后,我可以使用来自DB的主键,但在它持久化之前,所有新对象都有一个0的键.我把它作为一个单独的问题提出但是没有得到一个好的响应http:// stackoverflow. COM /问题/ 9782235 /实施-iequatable换POCO (2认同)
  • 我试过这个(实现了`IEquatable <T>`)并且它对代码的速度没有影响.此外,您谈论*unboxing*但您引用的代码中没有取消装箱.在你的结论清单中,选项#2并不清楚:它只说明它缺少*但不是它*是什么*.也许一些关于做什么的明确指示将是有用的. (2认同)