实体框架6 DbSet AddRange vs IDbSet Add - AddRange如何更快?

Ogg*_*las 8 c# entity-framework entity-framework-6

我正在家用电脑上玩Entity Framework 6,并决定尝试插入相当多的行,大约430k.

我的第一次尝试看起来像这样,是的,我知道它可以更好,但它仍然用于研究:

var watch = System.Diagnostics.Stopwatch.StartNew();
foreach (var event in group)
{
    db.Events.Add(event);
    db.SaveChanges();
}

var dbCount = db.Events.Count(x => x.ImportInformation.FileName == group.Key);

if (dbCount != group.Count())
{
    throw new Exception("Mismatch between rows added for file and current number of rows!");
}

watch.Stop();
Console.WriteLine($"Added {dbCount} events to database in {watch.Elapsed.ToString()}");
Run Code Online (Sandbox Code Playgroud)

我在晚上开始工作,当我下班回家时检查一下.这是结果:

在此输入图像描述

正如你所看到的,在前4小时41分钟内增加了64523个事件,但随后它变慢了很多,接下来的66985个事件花了14小时51分钟.我检查了数据库,程序仍然以极低的速度插入事件.然后我决定尝试DbSet的"新" AddRange方法.

我将我的模型从切换IDbSetDbSet并用以下方法替换了foreach循环:

db.Events.AddRange(group);
db.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我现在可以在大约30秒内添加60k +事件.它可能不是SqlBulkCopy快速但它仍然是一个巨大的进步.为实现这一目标,幕后发生了什么?我以为我SQL Server Profiler明天会查询查询,但是解释代码中的内容会很好.

Jon*_*nan 13

正如Jakub回答的那样,在每个添加的实体都没有帮助之后调用SaveChanges.但即使你把它移出去,你仍会遇到一些性能问题.这不会解决Add方法导致的性能问题.

添加vs AddRange

使用Add方法添加多个实体是一个非常常见的错误.事实上,这是InsctChanges方法的INSANELY缓慢.

  • 添加每条记录后添加方法DetectChanges.
  • 添加所有记录后的AddRange方法DetectChanges.

请参阅:实体框架 - 性能添加


它可能不是SqlBulkCopy的快速,但它仍然是一个巨大的进步

可以使性能非常接近SqlBulkCopy.

免责声明:我是项目实体框架扩展的所有者

(这个图书馆不是免费的)

通过允许您一次保存多个实体,该库可以提高代码的效率.支持所有批量操作:

  • BulkSaveChanges
  • BulkInsert
  • BulkUpdate
  • BulkDelete
  • BulkMerge
  • BulkSynchronize

例:

// 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 Primary Key
context.BulkMerge(customers, operation => {
   operation.ColumnPrimaryKeyExpression = 
        customer => customer.Code;
});
Run Code Online (Sandbox Code Playgroud)