我必须从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<Article> Articles { get; set; }
}
对于for循环中的每个项目,我都这样做:
db.Articles.Add(article);
在for循环之外我做:
db.SaveChanges();
它与我的本地SQLExpress服务器连接,但我想在调用SaveChanges之前没有任何内容,所以我猜服务器不会出现问题....
答案 0 :(得分:46)
根据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
答案 1 :(得分:19)
我将添加Kervin Ramen的评论说,如果你只是进行插入(没有更新或删除),那么你可以在对上下文进行任何插入之前安全地设置以下属性:
DbContext.Configuration.AutoDetectChangesEnabled = false;
DbContext.Configuration.ValidateOnSaveEnabled = false;
我的工作中有一次性批量导入问题。如果不设置上述属性,则向上下文添加大约7500个复杂对象需要花费30多分钟。设置上述属性(因此禁用EF检查和更改跟踪)会将导入减少到几秒钟。
但是,我再次强调,如果你正在插入,只使用它。如果需要将插入与更新/删除混合,则可以将代码拆分为两个路径,并禁用插入部分的EF检查,然后重新启用对更新/删除路径的检查。我已经成功地使用这种方法来解决慢DbSet.Add()
行为。
答案 2 :(得分:9)
工作单元中的每个项目都有开销,因为它必须检查(和更新)身份管理器,添加到各种集合等。
我要尝试的第一件事就是批量打入500组(改变那个数字以适应),每次都从一个新的(新的)对象上下文开始 - 否则你可以合理地期望伸缩性能。将其分成几批也可以防止巨石交易使一切停止。
除此之外; SqlBulkCopy的。它专为大型进口而设计,开销最小。但它不是EF。
答案 3 :(得分:5)
这里有一个非常容易使用和非常快速的扩展: https://efbulkinsert.codeplex.com/
它被称为“实体框架批量插入”。
扩展本身位于名称空间EntityFramework.BulkInsert.Extensions中。因此,使用
显示扩展方法addusing EntityFramework.BulkInsert.Extensions;
然后你可以这样做
context.BulkInsert(entities);
BTW - 如果由于某种原因你不想使用这个扩展,你也可以尝试而不是为每篇文章运行db.Articles.Add(article),每次创建几篇文章的列表然后使用AddRange (EF版本6中的新增功能,以及RemoveRange)将它们一起添加到dbcontext。
答案 4 :(得分:1)
我还没有真正尝试过这个,但我的逻辑是坚持使用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
嗯,我希望它有所帮助。