我正在使用Entity Framework来构建数据库。有两种型号; 工人和技能。每个工作人员都有零个或多个技能。我最初从某个地方的CSV文件中将这些数据读入内存,并将其存储在名为allWorkers
的字典中。接下来,我将数据写入数据库:
// Populate database
using (var db = new SolverDbContext())
{
// Add all distinct skills to database
db.Skills.AddRange(allSkills
.Distinct(StringComparer.InvariantCultureIgnoreCase)
.Select(s => new Skill
{
Reference = s
}));
db.SaveChanges(); // Very quick
var dbSkills = db.Skills.ToDictionary(k => k.Reference, v => v);
// Add all workers to database
var workforce = allWorkers.Values
.Select(i => new Worker
{
Reference = i.EMPLOYEE_REF,
Skills = i.GetSkills().Select(s => dbSkills[s]).ToArray(),
DefaultRegion = "wa",
DefaultEfficiency = i.TECH_EFFICIENCY
});
db.Workers.AddRange(workforce);
db.SaveChanges(); // This call takes 00:05:00.0482197
}
最后db.SaveChanges();
需要五分钟才能执行,我觉得这太长了。我在执行调用时运行了SQL Server Profiler,基本上我发现的是成千上万的调用:
INSERT [dbo].[SkillWorkers]([Skill_SkillId], [Worker_WorkerId])
VALUES (@0, @1)
向SkillWorkers
添加了16,027行,这是一个相当数量的数据,但无论如何都不是很大。有没有办法优化这段代码,所以它不需要5分钟才能运行?
更新:我查看了其他可能的重复项such as this one,但我认为它们不适用。首先,我不是在循环中批量添加任何东西。将每行添加到db.SaveChanges();
后,我只对db.Workers
进行一次调用。这应该是批量插入的最快方法。其次,我已将db.Configuration.AutoDetectChangesEnabled
设置为false
。 SaveChanges()
调用现在需要 00:05:11.2273888 (换句话说,大致相同)。我认为这并不重要,因为每一行都是新的,因此没有更改来检测。
我认为我正在寻找的是一种发布包含所有16,000种技能的单一UPDATE语句的方法。
答案 0 :(得分:1)
一种简单的方法是使用EntityFramework.BulkInsert扩展名。
然后你可以这样做:
// Add all workers to database
var workforce = allWorkers.Values
.Select(i => new Worker
{
Reference = i.EMPLOYEE_REF,
Skills = i.GetSkills().Select(s => dbSkills[s]).ToArray(),
DefaultRegion = "wa",
DefaultEfficiency = i.TECH_EFFICIENCY
});
db.BulkInsert(workforce);