我正在寻找插入 Entity Framework 的最快方法。
我之所以这样问,是因为您有一个活跃的TransactionScope
且插入量很大(超过4000个)。它可能持续10分钟以上(默认的事务超时),这将导致不完整的事务。
最佳答案
在对您的问题的评论中发表评论:
那是你最糟糕的事情!为每个记录调用SaveChanges()
会大大降低批量插入的速度。我将做一些简单的测试,很可能会提高性能:
SaveChanges()
。 SaveChanges()
。 SaveChanges()
并处理上下文并创建一个新的上下文。 对于批量插入,我正在尝试以下模式:
using (TransactionScope scope = new TransactionScope())
{
MyDbContext context = null;
try
{
context = new MyDbContext();
context.Configuration.AutoDetectChangesEnabled = false;
int count = 0;
foreach (var entityToInsert in someCollectionOfEntitiesToInsert)
{
++count;
context = AddToContext(context, entityToInsert, count, 100, true);
}
context.SaveChanges();
}
finally
{
if (context != null)
context.Dispose();
}
scope.Complete();
}
private MyDbContext AddToContext(MyDbContext context,
Entity entity, int count, int commitCount, bool recreateContext)
{
context.Set<Entity>().Add(entity);
if (count % commitCount == 0)
{
context.SaveChanges();
if (recreateContext)
{
context.Dispose();
context = new MyDbContext();
context.Configuration.AutoDetectChangesEnabled = false;
}
}
return context;
}
我有一个测试程序,该程序将560.000实体(9个标量属性,没有导航属性)插入数据库。使用此代码,它可以在不到3分钟的时间内运行。
为了提高性能,重要的是在“许多”记录(“许多”大约100或1000)之后调用
SaveChanges()
。它还提高了在SaveChanges之后处理上下文并创建新上下文的性能。这会清除所有实体的上下文,SaveChanges
不会这样做,实体仍然以Unchanged
状态附加到上下文。在上下文中,连接实体的大小不断增长,这会逐步降低插入速度。因此,一段时间后清除它会很有帮助。以下是我的560000个实体的一些度量值:
上面的第一个测试中的行为是性能是非常非线性的,并且随着时间的推移会大大降低。 (“很多小时”是一个估计,我从未完成此测试,在20分钟后停止在50.000个实体上。)这种非线性行为在所有其他测试中都不那么重要。