我使用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而不在每个实例上进行操作的任何想法?
答案 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