早上好。
今天,我遇到了EF 6和AddRange
方法的问题。有一个WPF应用程序可以处理约100000条记录。我编写了导入功能,该功能从.csv文件导入数据,但是有问题。
它看起来像这样:
private void FileImport()
{
//Open dialog to choose file
OpenFileDialog ofd = new OpenFileDialog();
string fileName = string.Empty;
if (ofd.ShowDialog() == true)
{
fileName = ofd.FileName;
}
if (!string.IsNullOrEmpty(fileName))
{
//getting all lines
var lines = File.ReadAllLines(fileName).ToList();
//File requirements says that there cannot be empty values in first element
if (lines.Any(line => line.Split(';')[0].Equals("null")))
{
MessageBox.Show("BLA BLA BLA");
}
else
{
List<List<string>> splitLines = new List<List<string>>();
//split lines into smaller list. For every sublist in list we will do things separatly in separate threads to get it faster.
for (int i = 0; i < lines.Count; i += 1000)
{
splitLines.Add(lines.GetRange(i, Math.Min(1000, lines.Count - i)));
}
var taskList = new List<Task>();
List<ut_katabcdx_file_filters> filterList = new List<ut_katabcdx_file_filters>();
foreach (var list in splitLines)
{
//define a Task
var t = new Task(() =>
{
foreach (var line in list)
{
var filters = line.Split(';');
//split line into elements array. It must have 6 elemets
if (filters.Count() == 6)
{
//Temporary declaration for parsing. If element that pretends to be decimals are empty we set its value to -100000.
decimal temp;
int tempi;
decimal? proga = filters[1].Equals("") ? -100000 : (decimal.TryParse(filters[1], out temp) ? (decimal?)temp : null);
decimal? progb = filters[2].Equals("") ? -100000 : (decimal.TryParse(filters[2], out temp) ? (decimal?)temp : null);
int? plan_sprz_rok = filters[3].Equals("") ? -100000 : (int.TryParse(filters[3], out tempi) ? (int?)tempi : null);
ut_katabcdx_file_filters filter = new ut_katabcdx_file_filters()
{
indeks = filters[0],
//produkty_iz = ProduktyIzChecked ? (filters[1].Equals("null") ? null : filters[1]) : string.Empty,
proga = ProgaChecked ? proga : -100000,
progb = ProgbChecked ? progb : -100000,
plan_sprz_rok = PlanSprzRokChecked ? plan_sprz_rok : -100000,
kat_tech = KatTechChecked ? (filters[4].Equals("null") ? null : filters[4]) : string.Empty,
kat_handl = KatHandlChecked ? (filters[5].Equals("null") ? null : filters[5]) : string.Empty,
};
filterList.Add(filter);
}
}
});
taskList.Add(t);
t.Start();
}
//wait for all tasks to end
Task.WaitAll(taskList.ToArray());
using (var ctx = new ABCDXContext())
{
ctx.ut_katabcdx_file_filters.AddRange(filterList);
ctx.SaveChanges();
string param_xml = GetParamXml();
Products = new ObservableCollection<ut_katabcdx_wytwor>(ctx.WytworFileUpdate(param_xml));
}
}
}
}
当我调试代码时,它在ctx.ut_katabcdx_file_filters.AddRange(filterList);
处停止,并且没有继续进行。我检查了filterList.Count
,大约有60000行。我也检查了数据库表,但是它是空的。
是因为大量数据还是我做某件事不正确? 我将非常感谢您提供任何建议。
答案 0 :(得分:0)
我同意DavidG关于尝试使用AddRange
插入60k记录的评论。会很慢。您将只需要等待它完成即可,或者找到其他选择。
我发现当您定期致电Context
时,您的SaveChanges
会更快乐。看来,在变更跟踪器中堆积大量项目会严重打击性能。
因此您可以执行以下操作:
using (var ctx = new ABCDXContext())
{
var count = 0;
foreach (var filter in filterList)
{
ctx.ut_katabcdx_file_filters.Add(filter);
count++;
if (count > 100)
{
ctx.SaveChanges();
count = 0;
}
}
if (count > 0)
ctx.SaveChanges();
string param_xml = GetParamXml();
Products = new ObservableCollection<ut_katabcdx_wytwor>(ctx.WytworFileUpdate(param_xml));
}
...只是将保存分成几个部分。您可以将count
调整为一个平衡方案性能的值。
This answer提供了您可以尝试的其他建议。那里的评论表明效果很好。