我试图从一个130万行的表中获取所有ID,然后使用Entity Framework将它们插入另一个数据库中的另一个表中。当我使用SSIS进行此操作时,它在5分钟内完成,而当我使用Entity Framework进行操作时,则需要3.5个小时。
我已经阅读了几篇有关慢速EF插入的资料,它们似乎表明我应该关闭“启用自动检测更改”功能,并且应该避免使用我尝试过的循环(不带循环)和不带循环(循环),这仍然需要很长时间。
我没有循环的代码如下:
_DB2context.Configuration.AutoDetectChangesEnabled = false;
_DB2context.Table2.AddRange(_DB1context.Table1.Select(m => m.Id)
.Select(pen => new Table2() { Checked = false, Id = pen }));
await _DB2context.SaveChangesAsync();
第三行执行大约需要3.5个小时。当我尝试使用循环执行此操作时,我的代码是:
var idList = _DB1context.Table1.Select(m => m.Id).ToList();
int i = 0;
foreach (var id in idList)
{
i++;
_DB2context.Table2.Add(new Table2() {Checked = false, Id = id});
if ((i % 10000)==0)
{
await _DB2context.SaveChangesAsync();
}
}
是否有明显的我做错事情,并且有什么方法可以使它在运行时更像ssis?
答案 0 :(得分:1)
实体框架为要保存的每个实体执行一次数据库往返。因此,如果您要插入130万行,它将使130万次数据库往返运行很慢。
正如@mjwills所指出的,您可以使用SqlBulkCopy
获得最佳性能。
免责声明:我是Entity Framework Extensions
的所有者该库不是免费的,但允许您执行所有批量操作,包括BulkSaveChanges
和BulkInsert
:
示例
// Easy to use
context.BulkSaveChanges();
// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);
// Perform Bulk Operations
context.BulkDelete(customers);
context.BulkInsert(customers);
context.BulkUpdate(customers);
// Customize Bulk Operations
context.BulkInsert(customers, options => {
options => options.IncludeGraph = true;
});
context.BulkMerge(customers, options => {
options.ColumnPrimaryKeyExpression =
customer => customer.Code;
});