提高初始化种子中DbSet的性能?

时间:2012-02-24 23:18:07

标签: entity-framework automapper

我使用AutoMapper将遗留数据库中的对象映射到EF代码中声明的新数据库:

  StartTimer("Map Customers");      
      var mfpCustomers = Mapper.Map<IEnumerable<LegacyDataModel.Customer>, IEnumerable<Customer>>(
        legacyEntities.Customers.Include(p => p.Demographics).ToList());
      StopAndPrintTimer("Map Customers");

      StartTimer("Iterate Customers");
      foreach (var p in mfpCustomers)
      {
        db.Customers.Add(p);       
      }
      StopAndPrintTimer("Iterate Customers");

每个人都需要花费最多的时间。我想直接映射到DbSet(db.Customer),而不是通过db.Customers.Add(p);进行预测。我没有想出如何做到这一点,因为没有像AddRange方法专门设计用于添加大量对象。我知道如何在SQL中使用基于集合的技术进行这些类型的转换,但这是一种疯狂的输入,因为智能感知在SSMS中的那些情况下效果不佳。

这段代码不需要超快,但每次我为数据库播种时都要等待一整分钟,这使得开发变得困难(并且由于新数据库的快速开发,它确实需要重新播种)。另请注意,由于这是种子方法,我不介意完全替换现有的Customers(因为没有)。所以在这方面它不需要像AddRange那样,因为我真的只是在创建一个新的集合。

关于如何提高性能的任何想法? 关于如何将整个集合直接映射到DbSet而不在每个实例上进行操作的任何想法?

1 个答案:

答案 0 :(得分:1)

每次调用db.Customers.Add(p)时,EF都会进行DetectChanges调用,以查看实体图中是否有任何内容发生了变化。在对其他实体进行更改后调用Add时,这有助于使事情按预期工作。但是,如果上下文中有很多实体,则DetectChanges会变慢 - 它在实体数量上有O(n)时间。因此,如果您暂时将这些自动调用转为DetectChanges,那么在您拥有它的情况下会产生很大的不同。例如:

try
{
    context.Configuration.AutoDetectChangesEnabled = false;

    foreach (var p in mfpCustomers)  
    {  
        db.Customers.Add(p);         
    }  
}
finally
{
    context.Configuration.AutoDetectChangesEnabled = true;
}

您可以在此处找到更多详细信息: http://blogs.msdn.com/b/adonet/archive/2011/02/06/using-dbcontext-in-ef-feature-ctp5-part-12-automatically-detecting-changes.aspx