EF AddRange方法不适用于大数据

时间:2019-05-08 12:19:48

标签: c# wpf entity-framework

早上好。

今天,我遇到了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行。我也检查了数据库表,但是它是空的。

是因为大量数据还是我做某件事不正确? 我将非常感谢您提供任何建议。

1 个答案:

答案 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提供了您可以尝试的其他建议。那里的评论表明效果很好。