Обработка плоских данных CSV с высокой производительностью

#c# #csv

#c# #csv

Вопрос:

Мне нужны некоторые идеи, как увеличить производительность для чтения из файла CSV.

Я создал одну версию, которая работает хорошо, но производительность больше не желательна, когда у нас более 200 000 строк в CSV, время обработки занимает много времени, а процесс импорта будет очень медленным по производительности.

Я покажу небольшой фрагмент файла CSV:

 "Oliver Russi,oliverrussi31@somecompany1.com,John Brown,VIVW8562,BankName8,72368997,581349,AUD"
"Oliver Russi,oliverrussi31@somecompany1.com,John Brown,VIVW8562,BankName3,77960361,402376,EUR"
"Oliver Russi,oliverrussi31@somecompany1.com,John Brown,VIVW8562,BankName5,73992264,302171,AUD"
"Oliver Russi,oliverrussi31@somecompany1.com,John Brown,VIVW8562,BankName1,00748228,313303,GBP"
"Oliver Russi,oliverrussi31@somecompany1.com,Alberto John,XIWVW8623,BankName8,32368997,381349,AUD"
"Oliver Russi,oliverrussi31@somecompany1.com,Alberto John,XIWVW8623,BankName3,56960361,602376,EUR"

                                                
"Sale agent 1,sale_agent1@somecompany3831.com,Client Name 1 of Sale Agent 1,VIVW8562, BankName8,72368997,581349,AUD"
"Sale agent 1,sale_agent1@somecompany3831.com, Client Name 1 of Sale Agent 1, VIVW8562,BankName3,77960361,402376,EUR"
"Sale agent 1,sale_agent1@somecompany3831.com, Client Name 1 of Sale Agent 1, VIVW8562,BankName5,73992264,302171,AUD"
"Sale agent 1,sale_agent1@somecompany3831.com, Client Name 2 of Sale Agent 1, XIWVW8623, BankName8,32368997,381349,AUD"
"Sale agent 1,sale_agent1@somecompany3831.com, Client Name 2 of Sale Agent 1, XIWVW8623, BankName3,56960361,602376,EUR"
"Sale agent 1,sale_agent1@somecompany3831.com, Client Name 2 of Sale Agent 1, XIWVW8623, BankName5,88992264,702171,AUD"
"Sale agent 1,sale_agent1@somecompany3831.com, Client Name 2 of Sale Agent 1, XIWVW8623, BankName1,97748228,913303,GBP"                             
"Sale agent 1,sale_agent1@somecompany3831.com, Client Name 2 of Sale Agent 1, XIWVW8623, BankName2,44648228,223334,EUR"                             
"Sale agent 2,sale_agent2@somecompany382.com, Client Name 1 of Sale agent 2, VIVW8562, BankName8,72368997,581349,AUD"
"Sale agent 2,sale_agent2@somecompany382.com, Client Name 1 of Sale agent 2, VIVW8562, BankName3,77960361,402376,EUR"
"Sale agent 2,sale_agent2@somecompany382.com, Client Name 1 of Sale agent 2, VIVW8562, BankName5,73992264,302171,AUD"
"Sale agent 2,sale_agent2@somecompany382.com,Client Name 2 of Sale agent 2, XIWVW8623, BankName8,32368997,381349,AUD"
  

Требуемый результат, основанный на фрагменте CSV, является:
Список агентов по продажам, состоящий из 3 агентов по продажам,
у каждого из них есть список, состоящий из 2 клиентов, а у соответствующего клиента есть список банковских счетов.

Что-то вроде следующего:

   "Oliver Russi,oliverrussi31@somecompany1.com,
                John Brown, VIVW8562, 
                        BankName8,72368997,581349,AUD"
                        BankName3,77960361,402376,EUR"
                        BankName5,73992264,302171,AUD"
                        BankName1,00748228,313303,GBP"
  
  "Oliver Russi,oliverrussi31@somecompany1.com,
                Alberto John, XIWVW8623, 
                        BankName8,32368997,381349,AUD"
                        BankName3,56960361,602376,EUR"
                                                        
  "Sale agent 1,sale_agent1@somecompany3831.com,
                Client Name 1 of Sale Agent 1, VIVW8562, 
                        BankName8,72368997,581349,AUD"
                        BankName3,77960361,402376,EUR"
                        BankName5,73992264,302171,AUD"
  
  "Sale agent 1,sale_agent1@somecompany3831.com,
                Client Name 2 of Sale Agent 1, XIWVW8623, 
                        BankName8,32368997,381349,AUD"
                        BankName3,56960361,602376,EUR"
                        BankName5,88992264,702171,AUD"
                        BankName1,97748228,913303,GBP"                              
                        BankName2,44648228,223334,EUR"                              

  "Sale agent 2,sale_agent2@somecompany382.com,
                Client Name 1 of Sale agent 2, VIVW8562, 
                        BankName8,72368997,581349,AUD"
                        BankName3,77960361,402376,EUR"
                        BankName5,73992264,302171,AUD"
  
  "Sale agent 2,sale_agent2@somecompany382.com,
                Client Name 2 of Sale agent 2, XIWVW8623, 
                        BankName8,32368997,381349,AUD"
  

Мой новый улучшенный код с использованием словаря следующий:

 public SalesAgentList ToSalesAgentList(string fileName)
        {
            List<SalesAgent> lst_salesAgent = new List<SalesAgent>();
            SalesAgentList salesAgentList = new SalesAgentList(lst_salesAgent);

            try
            {
                lst_salesAgents.Clear();

                string skipStr = "SalesAgentName,SalesAgentEmailAddress,ClientName,ClientIdentifier,BankName,AccountNumber,SortCode,Currency";

                string[] fileContents = File.ReadAllLines(fileName, Encoding.UTF8);

                List<string> lst = fileContents.OfType<string>().ToList().Select(s => s.Replace(""", string.Empty)).ToList();

                lst.Remove(skipStr);

                ICollection<List<string>> t = (from i in (lst.Select(item => item.Split(',')))
                                               select new List<string> { i[0], i[1], i[2], i[3], i[4], i[5], i[6], i[7] }).Distinct().ToList();

                Dictionary<string, BankAccount> dct_clBancAccount = new Dictionary<string, BankAccount>();

                Dictionary<string, Dictionary<string, BankAccount>> clDictionary = new Dictionary<string, Dictionary<string, BankAccount>>();

                Dictionary<string, /*SaleAgent dictionary*/
                        Dictionary<string,/*Client dictionary*/
                                 Dictionary<string, BankAccount>/*Bank Account dictionary*/
                                  >
                          > tmp = new Dictionary<string, Dictionary<string, Dictionary<string, BankAccount>>>();

                foreach (List<string> itm in t)
                {
                    Dictionary<string, Dictionary<string, BankAccount>> tmp_clDictionary = new Dictionary<string, Dictionary<string, BankAccount>>();
                    Dictionary<string, BankAccount> tmp_dct_clBancAccount = new Dictionary<string, BankAccount>();

                    BankAccount clBankAccount = new BankAccount(itm[3], itm[4], itm[5], itm[6], itm[7]);

                    SalesAgentBuilder tmpSaleAgent = new SalesAgentBuilder();
                    tmpSaleAgent.SalesAgentName = itm[0];
                    tmpSaleAgent.SalesAgentEmailAddress = itm[1];

                    if (!tmp.ContainsKey(itm[0]))
                    {
                        dct_clBancAccount.Add(itm[5], clBankAccount);
                        tmp_dct_clBancAccount.Add(itm[5], clBankAccount);
                        tmp_clDictionary.Add(itm[3], tmp_dct_clBancAccount);
                        clDictionary.Add(itm[3], tmp_dct_clBancAccount);
                        tmp.Add(itm[0], tmp_clDictionary);
                    }
                    else
                    {
                        if (!dct_clBancAccount.ContainsKey(itm[5]))
                        {
                            Dictionary<string, BankAccount> tmpclBnkAccDictionary;
                            if (clDictionary.TryGetValue(itm[3], out tmpclBnkAccDictionary))
                            {
                                tmpclBnkAccDictionary.Add(itm[5], clBankAccount);
                                tmp_dct_clBancAccount.Add(itm[5], clBankAccount);
                            }
                        }
                    }
                }


//need to implement salesAgentList = tmp.ToList(); 

            }

            catch (Exception ex) { Console.WriteLine(ex.Message); }
            return salesAgentList;
        }
  

проблема:
Я попытался изменить часть кода foreach на parralel.foreach(), но я получаю следующую ошибку.
Просто для упоминания о обычном способе foreach, он не выдает ошибку.

 System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=mscorlib
  StackTrace:
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at SalesAgentFileRecordList.<>c__DisplayClass23_0.<ToSalesAgentList>b__3(List`1 itm)
   in D:docGHDevTest-Q3_vProcessCSV.cs:line 1139
  

любая помощь приветствуется.
Спасибо,

Комментарии:

1. какая строка выдает ошибку?

2. Не изобретайте велосипед и используйте одну из существующих библиотек синтаксического анализа CSV .

3. следующая строка:tmp.Add(itm[0], tmp_clDictionary);

4. Не пытайтесь просто добавить параллель. Для без хорошего понимания безопасности потоков. Вы делали какое-либо профилирование, чтобы увидеть, какая часть требует времени?

5. Сколько времени занимает файл. Строки чтения занимают 200 000 строк файла?