如何加速DbSet.Add()?

我必须从CSV文件导入大约30k行到我的SQL数据库,这可能需要20分钟。

使用分析器进行故障排除向我显示DbSet.Add占用的时间最多,但为什么呢?

我有这些Entity Framework Code-First类:

public class Article { // About 20 properties, each property doesn't store excessive amounts of data } public class Database : DbContext { public DbSet
Articles { get; set; } }

对于我的for循环中的每个项目,我做:

 db.Articles.Add(article); 

在for循环之外我做:

 db.SaveChanges(); 

它与我的本地SQLExpress服务器连接,但我想在SaveChanges被调用之前没有任何东西,所以我猜服务器不会出现问题….

工作单元中的每个项目都有开销,因为它必须检查(和更新)身份管理器,添加到各种集合等。

我要尝试的第一件事就是批量打入500组(改变那个数字以适应),每次从一个新的(新的)对象上下文开始 – 否则你可以合理地期望伸缩性能。 将其分成批次也可以防止巨石交易使一切停止。

除此之外; SqlBulkCopy的。 它专为大型import而设计,开销最小。 但它不是EF。

根据Kevin Ramen的评论(3月29日),我可以确认设置db.Configuration.AutoDetectChangesEnabled = false速度产生巨大影响

默认情况下,在2324项上运行Add()在我的机器上运行3分15秒,禁用自动检测导致操作在0.5秒内完成。

http://blog.larud.net/archive/2011/07/12/bulk-load-items-to-a-ef-4-1-code-first-aspx

我将添加Kervin Ramen的评论,说如果你只是进行插入(没有更新或删除),那么你可以在对上下文进行任何插入之前安全地设置以下属性:

 DbContext.Configuration.AutoDetectChangesEnabled = false; DbContext.Configuration.ValidateOnSaveEnabled = false; 

我在工作中遇到了一次性批量导入的问题。 如果不设置上述属性,则向上下文添加大约7500个复杂对象需要超过30分钟。 设置上述属性(禁用EF检查和更改跟踪)会将导入减少到秒。

但是,我再次强调,如果你正在插入,只使用它。 如果需要将插入与更新/删除混合,则可以将代码拆分为两个路径,并禁用插入部分的EF检查,然后重新启用对更新/删除路径的检查。 我成功地使用这种方法来解决缓慢的DbSet.Add()行为。

这里有一个非常容易使用和非常快速的扩展: https : //efbulkinsert.codeplex.com/

它被称为“entity framework批量插入”。

扩展本身位于名称空间EntityFramework.BulkInsert.Extensions中。 所以要显示扩展方法添加使用

 using EntityFramework.BulkInsert.Extensions; 

然后你就可以做到这一点

 context.BulkInsert(entities); 

BTW – 如果由于某种原因你不想使用这个扩展,你也可以尝试而不是为每篇文章运行db.Articles.Add(article),每次创建几篇文章的列表然后使用AddRange(new in EF版本6以及RemoveRange)将它们一起添加到dbcontext。

我还没有真正尝试过这个,但我的逻辑是坚持使用ODBC驱动程序将文件加载到datatable中,然后使用sql存储过程将表传递给过程。

对于第一部分,请尝试: http : //www.c-sharpcorner.com/UploadFile/mahesh/AccessTextDb12052005071306AM/AccessTextDb.aspx

对于第二部分,请尝试使用SQL过程: http : //www.builderau.com.au/program/sqlserver/soa/Passing-table-valued-parameters-in-SQL-Server-2008/0,339028455,339282577, 00.htm

并在c#中创建SqlCommnand对象并添加到其Parameters集合SqlParameter,即SqlDbType.Structured

好吧,我希望它有所帮助。